2011-11-05 148 views
2

我正在使用GPS座標排行榜的iPhone應用程序。我不需要精確的座標---實際上我並不想的座標是準確的,以保護用戶的隱私。有沒有簡單的方法讓GPS座標變得粗糙?

我指定的kCLLocationAccuracyThreeKilometers爲desiredAccuracy,但是當GPS是活動的,似乎它也可以拿起設備的確切位置。

問題:有沒有簡單的算法可以用來使GPS數據更粗?說,使它粒度爲3公里。

如果我只是按比例縮小數字並刪除小數點並再次縮小它們,它會使它在世界某些地方比其他地方更粗糙。

謝謝!

+0

請記住,相似的長度有所不同。我的意思是在赤道附近(緯度〜0°),一個單一的經度是一個更大的距離,然後是靠近兩極的一個單一的經度。在極點(緯度+/- 90°)處,經度甚至失去了它的意義。 – Plap

回答

2

儘管Mark的回答很有用,但仍然沒有產生一致結果的公式,因爲它依賴於隨機數生成器。

我的好友爲此提供了最好的回答:

回合的緯度,經度取決於粒度最近顯著的身影,但是這將導致所有附近的某個位置的緯度/經度,風中相同的位置。該方法將使用緯度/經度中兩點之間的距離來計算緯度的四捨五入。使用下面的公式,並將路線設置爲0,那麼距離就是您的距離粒度。計算產生的新緯度/經度減去兩個緯度/經度以獲得緯度的舍入量。然後將標題設置爲90並重新計算並從舊中減去新的經緯度以獲得lon的舍入量。

而這裏的C++代碼:

class LocationUtility 
{ 
    public: static Location getLocationNow() 
    { 
    Location location; 

    if(context != null) 
    { 
     double latitude = 0; 
     double longitude = 0; 
     ::of_getCurrentLocation(&latitude, &longitude); 

     location.setLatitude(latitude); 
     location.setLongitude(longitude); 

     location = makeLocationCoarse(location); 
    } 

    return location; 
    } 

    public: static Location makeLocationCoarse(const Location& location) 
    { 
     double granularityInMeters = 3 * 1000; 
     return makeLocationCoarse(location, granularityInMeters); 
    } 

    public: static Location makeLocationCoarse(const Location& location, 
      double granularityInMeters) 
    { 
    Location courseLocation; 

    if(location.getLatitude() == (double)0 && 
     location.getLongitude() == (double)0) 
    { 
     // Special marker, don't bother. 
    } 
    else 
    { 
     double granularityLat = 0; 
     double granularityLon = 0; 
     { 
     // Calculate granularityLat 
     { 
      double angleUpInRadians = 0; 
      Location newLocationUp = getLocationOffsetBy(location, 
      granularityInMeters, angleUpInRadians); 

      granularityLat = location.getLatitude() - 
      newLocationUp.getLatitude(); 

      if(granularityLat < (double)0) 
      { 
      granularityLat = -granularityLat; 
      } 
     } 

     // Calculate granularityLon 
     { 
      double angleRightInRadians = 1.57079633; 
      Location newLocationRight = getLocationOffsetBy(location, 
      granularityInMeters, angleRightInRadians); 

      granularityLon = location.getLongitude() - 
      newLocationRight.getLongitude(); 

      if(granularityLon < (double)0) 
      { 
      granularityLon = -granularityLon; 
      } 
     } 
     } 

     double courseLatitude = location.getLatitude(); 
     double courseLongitude = location.getLongitude(); 
     { 
     if(granularityLon == (double)0 || granularityLat == (double)0) 
     { 
      courseLatitude = 0; 
      courseLongitude = 0; 
     } 
     else 
     { 
      courseLatitude = (int)(courseLatitude/granularityLat) * 
      granularityLat; 

      courseLongitude = (int)(courseLongitude/granularityLon) * 
      granularityLon; 
     } 
     } 
     courseLocation.setLatitude(courseLatitude); 
     courseLocation.setLongitude(courseLongitude); 
    } 

    return courseLocation; 
    } 

    // http://www.movable-type.co.uk/scripts/latlong.html 
    private: static Location getLocationOffsetBy(const Location& location, 
    double offsetInMeters, double angleInRadians) 
    { 
    Location newLocation; 

    double lat1 = location.getLatitude(); 
    double lon1 = location.getLongitude(); 

    lat1 = deg2rad(lat1); 
    lon1 = deg2rad(lon1); 

    double distanceKm = offsetInMeters/(double)1000; 
    const double earthRadiusKm = 6371; 

    double lat2 = asin(sin(lat1)*cos(distanceKm/earthRadiusKm) + 
     cos(lat1)*sin(distanceKm/earthRadiusKm)*cos(angleInRadians)); 

    double lon2 = lon1 + 
     atan2(sin(angleInRadians)*sin(distanceKm/earthRadiusKm)*cos(lat1), 
     cos(distanceKm/earthRadiusKm)-sin(lat1)*sin(lat2)); 

    lat2 = rad2deg(lat2); 
    lon2 = rad2deg(lon2); 

    newLocation.setLatitude(lat2); 
    newLocation.setLongitude(lon2); 

    return newLocation; 
    } 

    private: static double rad2deg(double radians) 
    { 
    static double ratio = (double)(180.0/3.141592653589793238); 
    return radians * ratio; 
    } 

    private: static double deg2rad(double radians) 
    { 
    static double ratio = (double)(180.0/3.141592653589793238); 
    return radians/ratio; 
    } 

    /* 
    public: static void testCoarse() 
    { 
    Location vancouver(49.2445, -123.099146); 
    Location vancouver2 = makeLocationCoarse(vancouver); 

    Location korea(37.423938, 126.692488); 
    Location korea2 = makeLocationCoarse(korea); 

    Location hiroshima(34.3937, 132.464); 
    Location hiroshima2 = makeLocationCoarse(hiroshima); 

    Location zagreb(45.791958, 15.935786); 
    Location zagreb2 = makeLocationCoarse(zagreb); 

    Location anchorage(61.367778, -149.900208); 
    Location anchorage2 = makeLocationCoarse(anchorage); 
    }*/ 
}; 
2

如果假設地球是一個球體(基本上適用於這個問題),這非常類似於上一個問題 Rounding Lat and Long to Show Approximate Location in Google Maps

,那麼你只需要計算一個位置,這是從一個特定的角度距離給予經緯度。選擇距離和(隨機)方向,並使用距離公式計算新位置。

這裏有相反的問題的很好的討論(二緯度/經度點之間的距離):http://mathforum.org/library/drmath/view/51756.html

它應該是相對直接從那裏去尋找一個點具有指定距離指定點。

0

我嘗試implemente在Ruby,但在我的情況的解決方案,粗協調VS現實有巨大的差異。粗略座標僅在經緯度變化時變化,但當緯度保持不變並且長時間移動時,粗略保持不變。如果有人可以檢查下面的代碼,也許我做了一個錯誤的編碼。

class CoarseLocation 

    AREA_LIMIT = 1000 

    class << self 

    def make_location_coarse(lat, lon) 

     if lat.nil? && lon.nil? 
     raise InvalidParamsError 
     end 

     location = [lat.to_f, lat.to_f] 

     new_location_up = get_location_by_offset(location, AREA_LIMIT, 0) 

     granularityLat = location[0] - new_location_up[0] 

     if granularityLat < 0 
     granularityLat = -granularityLat 
     end 


     new_location_right = get_location_by_offset(location, AREA_LIMIT, 1.57079633) 

     granularityLon = location[1] - new_location_right[1] 

     if(granularityLon < 0) 
     granularityLon = -granularityLon 
     end 

     course_lat = location[0] 
     course_lon = location[1] 

     if(granularityLat == 0.0) || (granularityLon == 0.0) 
     course_lat = 0 
     course_lon = 0 
     else 
     course_lat = (course_lat/granularityLat).to_i * granularityLat 
     course_lon = (course_lon/granularityLon).to_i * granularityLon 
     end 

     [course_lat, course_lon] 
    end 

    def get_location_by_offset(location, offset, angle) 
     lat_radius = location[0] * Math::PI/180 
     lon_radius = location[1] * Math::PI/180 

     distance = (offset/1000).to_f 
     earth_radius = 6371 

     lat_radius_1 = (Math::asin(Math::sin(lat_radius) * Math::cos(distance/earth_radius) + Math::cos(lat_radius) * Math::sin(distance/earth_radius) * Math::cos(angle))).to_f 
     lon_radius_1 = (lon_radius + Math::atan2(Math::sin(angle)*Math::sin(distance/earth_radius)*Math::cos(lat_radius), Math::cos(distance/earth_radius) - Math::sin(lat_radius)*Math::sin(lat_radius_1))).to_f 

     new_lat = lat_radius_1 * 180/Math::PI 
     new_lon = lon_radius_1 * 180/Math::PI 

     return [new_lat.to_f, new_lon.to_f] 

    end 
    end 
end 

位置字段總是包含2個元素的陣列,其中[0]是lat,[1]是long。

相關問題