【问题标题】:Calculating a MKMapRect that contains all pins计算包含所有引脚的 MKMapRect
【发布时间】:2012-09-01 23:08:33
【问题描述】:

我正在尝试放大一张地图,该地图专注于与该地图相关联的所有图钉。我已将这些信息保存在我的地图属性中。

我从这个开始,但它还没有工作:

    double maxLatitude = 0;
    double minLatitude = 0;

    double maxLongitude = 0;
    double minLongitude = 0;

    for (MKAnnotation *address in self.map.locations) {
        // Latitude
        if ([address.latitude doubleValue] > 0) {
            maxLatitude = MAX(maxLatitude, [address.latitude doubleValue]);
        }
        else {
            minLatitude = MAX(abs(minLatitude), abs([address.latitude doubleValue]));
        }

        // Longitude
        if ([address.longitude doubleValue] > 0) {
            maxLongitude = MAX(maxLongitude, [address.longitude doubleValue]);
        }
        else {
            minLongitude = MAX(abs(minLongitude), abs([address.longitude doubleValue]));
        }
    }
    double centerLatitude = (maxLatitude - abs(minLatitude)) / 2;
    centerLatitude *= [self calculateSignWithFirstValue:maxLatitude secondValue:minLatitude];

    double centerLongitude = (maxLongitude - abs(minLongitude)) / 2;
    centerLongitude *= [self calculateSignWithFirstValue:maxLongitude secondValue:minLongitude];

// 用坐标创建一些 MKMapRect?

我不认为我理解 MKMapRect,因为当我尝试做这样的事情时:

    CLLocationCoordinate2D theOrigin = CLLocationCoordinate2DMake(32, -117);
    MKMapRect mapRect;
    mapRect.origin = MKMapPointForCoordinate(theOrigin);
    mapRect.size = MKMapSizeMake(10, 10);

我被安排在海洋而不是圣地亚哥。不确定 MKMapRect 发生了什么。

【问题讨论】:

    标签: iphone


    【解决方案1】:
    /** 
     * Return a region covering all the annotations in the given array.
     * @param annotations Array of objects conforming to the <MKAnnotation> protocol.
     */
    +(MKCoordinateRegion) regionForAnnotations:(NSArray*) annotations 
    {
        double minLat=90.0f, maxLat=-90.0f;
        double minLon=180.0f, maxLon=-180.0f;
    
        for (id<MKAnnotation> mka in annotations) {
            if ( mka.coordinate.latitude  < minLat ) minLat = mka.coordinate.latitude;
            if ( mka.coordinate.latitude  > maxLat ) maxLat = mka.coordinate.latitude;
            if ( mka.coordinate.longitude < minLon ) minLon = mka.coordinate.longitude;
            if ( mka.coordinate.longitude > maxLon ) maxLon = mka.coordinate.longitude;
        }
    
        CLLocationCoordinate2D center = CLLocationCoordinate2DMake((minLat+maxLat)/2.0, (minLon+maxLon)/2.0);
        MKCoordinateSpan span = MKCoordinateSpanMake(maxLat-minLat, maxLon-minLon);
        MKCoordinateRegion region = MKCoordinateRegionMake (center, span);
    
        return region;
    }
    
    // usage
    MKCoordinateRegion region = [XXXX regionForAnnotations:self.mapView.annotations];
    [self.mapView setRegion:region animated:YES];
    

    MKMapView 缩放到离散间隔,这意味着如果您放大随机区域,它将选择最近的缩放间隔。这可能与图块分辨率有关,但 AFAIK 没有记录。

    【讨论】:

    • 这可能是一个愚蠢的问题,但是为什么你将起点设置为360和-360?
    • 其实——我认为经度值应该是±180°,纬度值应该是±90°
    • 谢谢尼尔斯博特。 @Crystal我设置±360°的原因只是一个足够大的数字来强制循环中的新值。这也有在没有注释时返回整个地图的效果。
    • +1 用于“setRegion:”的未记录行为以及它缩放到离散缩放间隔的事实。试图弄清楚这种行为而发疯了。
    • 建议改进。对 max 和 min 使用 KVC Collection 运算符来简化 for 循环。例如:maxLat = [[annotations valueForKeyPath:@"@max.latitude"] doubleValue];
    【解决方案2】:

    只是为了解释您关于在圣地亚哥上空创建MKMapRect 并最终进入海洋的问题的第二部分......

    首先,坐标32, -117 仅“靠近”圣地亚哥。
    实际上,它在南边几公里处,在距墨西哥西海岸几公里的太平洋上。

    另请注意,在MKMapRect 中,origin 是矩形的左上角(不是中心),因此生成的矩形不完全包括您指定的坐标周围的区域。

    另一个真正的问题是跨度大小设置为MKMapSizeMake(10, 10)
    MKMapSize 使用MKMapPoint 单位(不是度、米、英里、公里等)。
    地图点等于的距离(以米为单位)因纬度而异。

    在纬度3210 地图点对应于1.261110(您可以使用 MapKit 函数 MKMetersPerMapPointAtLatitude 使用 10.0 * MKMetersPerMapPointAtLatitude(32) 计算)。

    因此,正在创建的地图矩形位于墨西哥西海岸附近,大小约为 1.26 x 1.26 。因此,您只能看到海洋(直到您放大很多)。

    虽然您可以使用上述函数将米转换为地图点并创建MKMapRect,但使用采用常规坐标(以度为单位的纬度和经度)的MKCoordinateRegionMakeWithDistance 函数和所需的宽度和高度(以米为单位),因此所有计算都由地图视图处理。

    【讨论】:

      【解决方案3】:

      我感觉 Jano 的答案也很完美,但为了多样化,这里有另一种解决方案。这是我通常用来放大给定注释的方法:

      -(void)zoomToFitMapAnnotations:(MKMapView *)mapView {
          if([mapView.annotations count] == 0)
              return;
      
          CLLocationCoordinate2D topLeftCoord;
          topLeftCoord.latitude = -90;
          topLeftCoord.longitude = 180;
      
          CLLocationCoordinate2D bottomRightCoord;
          bottomRightCoord.latitude = 90;
          bottomRightCoord.longitude = -180;
      
          for(MKPointAnnotation *annotation in mapView.annotations)
          {
              topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
              topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
      
              bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
              bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
          }
      
          MKCoordinateRegion region;
          region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
          region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
          region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1;
          region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1; 
      
          region = [mapView regionThatFits:region];
          [mapView setRegion:region animated:YES];
      }
      

      【讨论】:

        【解决方案4】:

        从 iOS 7 开始,有一种更简单的方法可以做到这一点:

        mapView.showAnnotations(mapView.showAnnotations, animated: true)

        希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 2020-01-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-30
          相关资源
          最近更新 更多