Tính toán Vĩ độ / Kinh độ X từ điểm?


46

Tôi muốn tìm một điểm vĩ độ và kinh độ cho một mang, một khoảng cách, và một vĩ độ và kinh độ bắt đầu.

Điều này dường như ngược lại với câu hỏi này ( Khoảng cách giữa các điểm lat / long ).

Tôi đã xem xét công thức haversine và nghĩ rằng nó gần đúng với thế giới có lẽ đã đủ gần.

Tôi giả sử rằng tôi cần giải quyết công thức haversine cho lat / long chưa biết của mình, điều này có đúng không? Có bất kỳ trang web tốt nói về loại điều này? Có vẻ như nó sẽ là phổ biến, nhưng googling của tôi chỉ đưa ra các câu hỏi tương tự như câu hỏi ở trên.

Những gì tôi thực sự tìm kiếm chỉ là một công thức cho việc này. Tôi muốn để cho nó một bắt đầu từ lat / lng, một mang, và một khoảng cách (dặm hoặc km) và tôi muốn để có được ra khỏi nó một lat / lng cặp đại diện cho một trong những nơi có thể đã kết thúc thăm họ đi du lịch cùng tuyến đường đó.


Bạn đang tìm kiếm một công cụ thực hiện điều này (như pe.dll của Esri) hay công thức?
Kirk Kuykendall

Xin lỗi tôi không cụ thể ... Tôi đang tìm kiếm một công thức. Tôi sẽ cập nhật câu hỏi của tôi để cụ thể hơn.
Jason Whitehorn

Bunch của các mẫu toán đã được xử lý ở đây <a href=" Movable-type.co.uk/scripts/latlong.html"> Tính khoảng cách, phương hướng và nhiều thứ khác giữa các điểm Vĩ độ / Kinh độ </a> bao gồm giải pháp cho "Đích đến điểm cho khoảng cách và mang từ điểm bắt đầu ".
Stephen Quan

1
Liên quan chặt chẽ: gis.stackexchange.com/questions/2951/ .
whuber

đây là trang liên kết đến lat / tính toán dài [Lat / tính toán dài] ( movable-type.co.uk/scripts/latlong.html ) cũng trang này Lat / tính toán lâu có một mã số + máy tính
Abo gaseem

Câu trả lời:


21

Tôi tò mò về kết quả từ công thức này so với pe.dll của Esri .

( trích dẫn ).

Một điểm {lat, lon} là một khoảng cách d trên radial tc từ điểm 1 nếu:

 lat=asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc))
 IF (cos(lat)=0)
    lon=lon1      // endpoint a pole
 ELSE
    lon=mod(lon1-asin(sin(tc)*sin(d)/cos(lat))+pi,2*pi)-pi
 ENDIF

Thuật toán này được giới hạn trong khoảng cách sao cho dlon <pi / 2, tức là những khoảng cách kéo dài dưới một phần tư chu vi của trái đất theo kinh độ. Một thuật toán hoàn toàn chung, nhưng phức tạp hơn là cần thiết nếu khoảng cách lớn hơn được cho phép:

 lat =asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc))
 dlon=atan2(sin(tc)*sin(d)*cos(lat1),cos(d)-sin(lat1)*sin(lat))
 lon=mod( lon1-dlon +pi,2*pi )-pi

Đây là một trang html để thử nghiệm .


Cảm ơn bạn đã trả lời nhanh chóng. Hãy để tôi tiêu hóa một số thông tin này, và tôi sẽ liên lạc lại với bạn. Trên bề mặt, mặc dù, điều này trông tại chỗ.
Jason Whitehorn

1
Tôi đã thử trường hợp trực tiếp bằng cách sử dụng pe.dll (thực sự là libpe.so trên solaris) sau khi lấy khoảng cách và góc phương vị chuyển tiếp từ trang html cho 32N, 117W đến 40N, 82W. Sử dụng 32N, 117W, d = 3255.056515890041, azi = 64.24498012065699, tôi đã nhận được 40N, 82W (thực tế là 82.00000000064).
mkennedy

3
Tuyệt vời! Cảm ơn bạn rất nhiều vì liên kết đến bài viết về Công thức Hàng không của Ed Williams, tôi chưa từng thấy điều này trước đây nhưng cho đến nay nó đã được chứng minh là một bài đọc tuyệt vời. Chỉ cần một lưu ý cho bất cứ ai nhìn vào điều này trong tương lai, đầu vào và đầu ra của công thức này là TẤT CẢ theo radian, thậm chí là khoảng cách.
Jason Whitehorn

1
Đơn vị khoảng cách trong công thức này là gì?
Karthik Murugan

1
Phần giới thiệu của @KarthikMurugan Ed cho biết các đơn vị khoảng cách tính bằng radian dọc theo một vòng tròn lớn.
Kirk Kuykendall

18

Nếu bạn đang ở trong một mặt phẳng, thì thời điểm đó là r mét tại một mang của một độ đông bắc đang di dời bởi r * cos (a) theo hướng bắc và r * sin (a) theo hướng đông. (Những tuyên bố này ít nhiều xác định sin và cos.)

Mặc dù bạn không ở trên máy bay - bạn đang làm việc trên bề mặt của một hình elip cong mô hình bề mặt Trái đất - bất kỳ khoảng cách nào dưới vài trăm km bao phủ một phần nhỏ của bề mặt mà hầu hết các mục đích thực tế đều có thể được coi là phẳng. Biến chứng duy nhất còn lại là một độ kinh độ không bao gồm khoảng cách tương tự như một độ vĩ độ. Trong mô hình Trái đất hình cầu, một độ kinh độ chỉ là cos (vĩ độ) miễn là một độ vĩ độ. (Trong một mô hình ellipsoidal, đây vẫn là một xấp xỉ xuất sắc, tốt cho khoảng 2,5 con số có ý nghĩa.)

Cuối cùng, một độ vĩ độ xấp xỉ 10 ^ 7/90 = 111.111 mét. Bây giờ chúng tôi có tất cả các thông tin cần thiết để chuyển đổi mét sang độ:

Sự dịch chuyển về phía bắc là r * cos (a) / 111111 độ;

Sự dịch chuyển về phía đông là r * sin (a) / cos (vĩ độ) / 111111 độ.

Ví dụ: ở vĩ độ -0.31399 độ và chịu lực a = 30 độ đông bắc, chúng ta có thể tính toán

cos(a) = cos(30 degrees) = cos(pi/6 radians) = Sqrt(3)/2 = 0.866025.
sin(a) = sin(30 degrees) = sin(pi/6 radians) = 1/2 = 0.5.
cos(latitude) = cos(-0.31399 degrees) = cos(-0.00548016 radian) = 0.999984984.
r = 100 meters.
east displacement = 100 * 0.5 / 0.999984984 / 111111 = 0.000450007 degree.
north displacement = 100 * 0.866025 / 111111 = 0.000779423 degree.

Từ đâu, bắt đầu từ (-78.4437, -0.31399), địa điểm mới là (-78.4437 + 0.00045, -0.31399 + 0.0007794) = (-78.4432, -0.313211).

Một câu trả lời chính xác hơn, trong hệ thống tham chiếu ITRF00 hiện đại, là (-78,4433, -0.313207): đây là 0,43 mét so với câu trả lời gần đúng, chỉ ra sai số xấp xỉ 0,43% trong trường hợp này. Để đạt được độ chính xác cao hơn, bạn phải sử dụng các công thức khoảng cách elip (phức tạp hơn nhiều) hoặc phép chiếu tuân thủ độ chính xác cao với độ phân kỳ bằng 0 (sao cho ổ đỡ là chính xác).


2
+1 để hiểu đúng ngữ cảnh toán học (nghĩa là mặt phẳng cục bộ của nó)
Frank Conry

4

Nếu bạn cần một giải pháp JavaScript, hãy xem xét những điều nàyfunctionscâu đố này :

var gis = {
  /**
  * All coordinates expected EPSG:4326
  * @param {Array} start Expected [lon, lat]
  * @param {Array} end Expected [lon, lat]
  * @return {number} Distance - meter.
  */
  calculateDistance: function(start, end) {
    var lat1 = parseFloat(start[1]),
        lon1 = parseFloat(start[0]),
        lat2 = parseFloat(end[1]),
        lon2 = parseFloat(end[0]);

    return gis.sphericalCosinus(lat1, lon1, lat2, lon2);
  },

  /**
  * All coordinates expected EPSG:4326
  * @param {number} lat1 Start Latitude
  * @param {number} lon1 Start Longitude
  * @param {number} lat2 End Latitude
  * @param {number} lon2 End Longitude
  * @return {number} Distance - meters.
  */
  sphericalCosinus: function(lat1, lon1, lat2, lon2) {
    var radius = 6371e3; // meters
    var dLon = gis.toRad(lon2 - lon1),
        lat1 = gis.toRad(lat1),
        lat2 = gis.toRad(lat2),
        distance = Math.acos(Math.sin(lat1) * Math.sin(lat2) +
            Math.cos(lat1) * Math.cos(lat2) * Math.cos(dLon)) * radius;

    return distance;
  },

  /**
  * @param {Array} coord Expected [lon, lat] EPSG:4326
  * @param {number} bearing Bearing in degrees
  * @param {number} distance Distance in meters
  * @return {Array} Lon-lat coordinate.
  */
  createCoord: function(coord, bearing, distance) {
    /** http://www.movable-type.co.uk/scripts/latlong.html
    * φ is latitude, λ is longitude, 
    * θ is the bearing (clockwise from north), 
    * δ is the angular distance d/R; 
    * d being the distance travelled, R the earth’s radius*
    **/
    var 
      radius = 6371e3, // meters
      δ = Number(distance) / radius, // angular distance in radians
      θ = gis.toRad(Number(bearing));
      φ1 = gis.toRad(coord[1]),
      λ1 = gis.toRad(coord[0]);

    var φ2 = Math.asin(Math.sin(φ1)*Math.cos(δ) + 
      Math.cos(φ1)*Math.sin(δ)*Math.cos(θ));

    var λ2 = λ1 + Math.atan2(Math.sin(θ) * Math.sin(δ)*Math.cos(φ1),
      Math.cos(δ)-Math.sin(φ1)*Math.sin(φ2));
    // normalise to -180..+180°
    λ2 = (λ2 + 3 * Math.PI) % (2 * Math.PI) - Math.PI; 

    return [gis.toDeg(λ2), gis.toDeg(φ2)];
  },
  /**
   * All coordinates expected EPSG:4326
   * @param {Array} start Expected [lon, lat]
   * @param {Array} end Expected [lon, lat]
   * @return {number} Bearing in degrees.
   */
  getBearing: function(start, end){
    var
      startLat = gis.toRad(start[1]),
      startLong = gis.toRad(start[0]),
      endLat = gis.toRad(end[1]),
      endLong = gis.toRad(end[0]),
      dLong = endLong - startLong;

    var dPhi = Math.log(Math.tan(endLat/2.0 + Math.PI/4.0) / 
      Math.tan(startLat/2.0 + Math.PI/4.0));

    if (Math.abs(dLong) > Math.PI) {
      dLong = (dLong > 0.0) ? -(2.0 * Math.PI - dLong) : (2.0 * Math.PI + dLong);
    }

    return (gis.toDeg(Math.atan2(dLong, dPhi)) + 360.0) % 360.0;
  },
  toDeg: function(n) { return n * 180 / Math.PI; },
  toRad: function(n) { return n * Math.PI / 180; }
};

Vì vậy, nếu bạn muốn tính toán tọa độ mới, nó có thể như vậy:

var start = [15, 38.70250];
var end = [21.54967, 38.70250];
var total_distance = gis.calculateDistance(start, end); // meters
var percent = 10;
// this can be also meters
var distance = (percent / 100) * total_distance;
var bearing = gis.getBearing(start, end);
var new_coord = gis.createCoord(icon_coord, bearing, distance);

2

Tôi đã làm việc này trong ObjectiveC. Chìa khóa ở đây là biết rằng bạn cần điểm lat / lng tính bằng radian và bạn cần chuyển đổi chúng trở lại lat / lng sau khi áp dụng phương trình. Ngoài ra, biết rằng khoảng cách và tc là bằng radian.

Đây là phương trình ban đầu:

 lat=asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc))
 IF (cos(lat)=0)
    lon=lon1      // endpoint a pole
 ELSE
    lon=mod(lon1-asin(sin(tc)*sin(d)/cos(lat))+pi,2*pi)-pi
 ENDIF

Ở đây, nó được triển khai trong ObjC trong đó radian là radian được đo ngược chiều kim đồng hồ từ N (ví dụ PI / 2 là W, PI là S, 2 PI / 3 là E) và khoảng cách tính bằng km.

+ (CLLocationCoordinate2D)displaceLatLng:(CLLocationCoordinate2D)coordinate2D withRadian:(double)radian
                            withDistance:(CGFloat)distance {
  double lat1Radians = coordinate2D.latitude * (M_PI / 180);
  double lon1Radians = coordinate2D.longitude * (M_PI / 180);
  double distanceRadians = distance / 6371;
  double lat = asin(sin(lat1Radians)*cos(distanceRadians)+cos(lat1Radians)*sin(distanceRadians)
      *cos(radian));
  double lon;
  if (cos(lat) == 0) {
    lon = lon1Radians;
  } else {
    lon = fmodf((float) (lon1Radians - asin(sin(radian) * sin(distanceRadians) / cos(lat)) + M_PI),
        (float) (2 * M_PI)) - M_PI;
  }
  double newLat = lat * (180 / M_PI);
  double newLon = lon * (180 / M_PI);
  return CLLocationCoordinate2DMake(newLat, newLon);
}

Tôi đang tìm kiếm một giải pháp mà tôi muốn để có được 4 lat, chờ đợi từ điểm mà tôi đứng tới 50 dặm về phía bắc, 50 dặm về phía tây, 50 dặm về phía đông và vân vân ... Trong câu trả lời ở trên, bạn có thể giải thích làm thế nào tôi có thể đạt được điều này ?
Rahul Vyas

1

Nếu bạn quan tâm đến độ chính xác tốt hơn, có Vincenty . (Liên kết là biểu mẫu 'trực tiếp', chính xác là những gì bạn đang theo đuổi).

Có khá nhiều triển khai hiện có, nếu bạn đang theo mã.

Ngoài ra, một câu hỏi: Bạn không cho rằng khách du lịch duy trì cùng một lực cho toàn bộ chuyến đi, phải không? Nếu vậy, thì các phương pháp này không trả lời đúng câu hỏi. (Bạn nên chiếu tốt hơn cho người đánh bóng, vẽ một đường thẳng, sau đó bỏ chiếu kết quả.)


Câu hỏi rất hay, mặc dù từ ngữ trong câu hỏi của tôi có thể chỉ ra rằng tôi đang tính toán một điểm đến cho một khách du lịch, nhưng tôi thì không. Điểm tốt mặc dù. Đây là chủ yếu vì vậy mà tôi có thể tính toán một khu vực ranh giới (trên một trật tự nhỏ, nói 50 dặm) ... Tôi hy vọng rằng có ý nghĩa.
Jason Whitehorn

gis.stackexchange.com/questions/3264/ đã có cùng một câu hỏi (xây dựng các khu vực giới hạn từ một điểm & khoảng cách)
Dan S.

0

Đây là một giải pháp Python:

    def displace(self, theta, distance):
    """
    Displace a LatLng theta degrees counterclockwise and some
    meters in that direction.
    Notes:
        http://www.movable-type.co.uk/scripts/latlong.html
        0 DEGREES IS THE VERTICAL Y AXIS! IMPORTANT!
    Args:
        theta:    A number in degrees.
        distance: A number in meters.
    Returns:
        A new LatLng.
    """
    theta = np.float32(theta)

    delta = np.divide(np.float32(distance), np.float32(E_RADIUS))

    def to_radians(theta):
        return np.divide(np.dot(theta, np.pi), np.float32(180.0))

    def to_degrees(theta):
        return np.divide(np.dot(theta, np.float32(180.0)), np.pi)

    theta = to_radians(theta)
    lat1 = to_radians(self.lat)
    lng1 = to_radians(self.lng)

    lat2 = np.arcsin( np.sin(lat1) * np.cos(delta) +
                      np.cos(lat1) * np.sin(delta) * np.cos(theta) )

    lng2 = lng1 + np.arctan2( np.sin(theta) * np.sin(delta) * np.cos(lat1),
                              np.cos(delta) - np.sin(lat1) * np.sin(lat2))

    lng2 = (lng2 + 3 * np.pi) % (2 * np.pi) - np.pi

    return LatLng(to_degrees(lat2), to_degrees(lng2))

-2

Tôi sử dụng cách tiếp cận được mô tả dưới đây trong việc xác định tọa độ tiếp theo cho ổ đỡ và khoảng cách từ tọa độ trước. Tôi có vấn đề về độ chính xác với cách tiếp cận khác mà tôi đọc được từ internet.

Tôi sử dụng điều này trong việc xác định diện tích đất, là một đa giác và vẽ đồ thị đa giác đó trong google earth. Một Tiêu đề đất có vòng bi và khoảng cách được viết theo cách này: "NorthOrSouth x độ y phút EastOrWest, z mét đến điểm n;".

Vì vậy, bắt đầu từ tọa độ đã cho của điểm tham chiếu, trước tiên tôi tính khoảng cách trên một vĩ độ một độ và kinh độ một độ bằng công thức haversine vì điều này thay đổi tùy theo vị trí. Sau đó, tôi xác định tọa độ tiếp theo từ công thức lượng giác sin và cos.

Dưới đây là javascript:

var mapCenter = new google.maps.LatLng(referencePointLatitude, referencePointLongitude); //the ref point lat and lon must be given, usually a land mark (BLLM)
var latDiv = latDiv(mapCenter); //distance per one degree latitude in this location
var lngDiv = lngDiv(mapCenter); //distance per one degree longitude in this location
var LatLng2 = NextCoord(PrevCoord,NorthOrSouth,x,y,EastOrWest,z); //next coordinate given the bearing and distance from previous coordinate
var Lat2 = LatLng2.lat(); //next coord latitude in degrees
var Lng2 = LatLng2.lng(); //next coord longitude in degrees
var polygon=[p1,p2,...,pn-1,pn,p1]; //p1,p2,etc. are the coordinates of points of the polygon, i.e. the land Title. Be sure to close the polygon to the point of beginning p1
var area = Area(polygon); //area of the polygon in sq.m.
function NextCoord(PrevCoord,NorthOrSouth,x,y,EastOrWest,z) {
  var angle = ( x + ( y / 60 ) ) * Math.PI / 180;
  var a = 1;
  var b = 1;
  if (NorthOrSouth == 'South') { a = -1; }
  if (EastOrWest == 'West') { b = -1; }
  var nextLat = PrevCoord.lat() +  ( a * z * Math.cos(angle) / latDiv );
  var nextLng = PrevCoord.lng() +  ( b * z * Math.sin(angle) / lngDiv );
  var nextCoord = new google.maps.LatLng(nextLat, nextLng);
  return nextCoord;
}
function latDiv(mapCenter) {
  var p1 = new google.maps.LatLng(mapCenter.lat()-0.5, mapCenter.lng());
  var p2 = new google.maps.LatLng(mapCenter.lat()+0.5, mapCenter.lng());
  return dist(p1,p2);
}
function lngDiv(mapCenter) {
  var p3 = new google.maps.LatLng(mapCenter.lat(), mapCenter.lng()-0.5);
  var p4 = new google.maps.LatLng(mapCenter.lat(), mapCenter.lng()+0.5);
  return dist(p3,p4);
}
function dist(pt1, pt2) {
    var dLat  = ( pt2.lat() - pt1.lat() ) * Math.PI / 180;
    var dLng = ( pt2.lng() - pt1.lng() ) * Math.PI / 180;
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +                 
            Math.cos(rad(pt1.lat())) * Math.cos(rad(pt2.lat())) *
            Math.sin(dLng/2) * Math.sin(dLng/2);
    var R = 6372800; //earth's radius
    var distance = R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    return distance;
}
function Area(polygon) {
  var xPts=[];
  for (i=1; i&lt;polygon.length; i++) {
    xPts[i-1] = ( polygon[i].lat() - polygon[0].lat() ) * latDiv;
  }
  var yPts=[];
  for (i=1; i&lt;polygon.length; i++) {
    yPts[i-1] = ( polygon[i].lng() - polygon[0].lng() ) * lngDiv;
  }
  var area = 0;
  j = polygon.length-2;
  for (i=0; i&lt;polygon.length-1; i++) {
    area = area +  ( xPts[j] + xPts[i] ) * ( yPts[j] - yPts[i] );
    j = i;
  }
  area = Math.abs(area/2);
  return area;
}

1
Công thức Cartesian cho khu vực đa giác mà bạn cố gắng áp dụng ở đây không áp dụng cho khoảng cách và góc được tính trên một bề mặt cong (chẳng hạn như hình cầu). Công thức này tạo ra một lỗi bổ sung bằng cách sử dụng vĩ độ và kinh độ như thể chúng là tọa độ Descartes. Các trường hợp duy nhất theo đó việc sử dụng nó có thể được xem xét sẽ chính xác là các trường hợp (đối với các đa giác rất nhỏ) trong đó công thức haversine là không cần thiết. Nhìn chung, có vẻ như mã này hoạt động quá nhiều khó khăn để không đạt được.
whuber
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.