2011-11-05 147 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。

相关问题