【问题标题】:How to fit a certain bounds consisting of NE and SW coordinates into the visible map view?如何将由 NE 和 SW 坐标组成的特定边界拟合到可见地图视图中?
【发布时间】:2011-12-13 21:39:53
【问题描述】:

我需要在地图中设置一定的界限。我通过调用谷歌地理编码器并读取看起来像这样的视口属性来获得界限:

{
    northeast =     {
        lat = "30.4212235";
        lng = "-97.486942";
    };
    southwest =     {
        lat = "30.1128403";
        lng = "-97.99917959999999";
    };
}

然后我将它们转换为 CLLocationCoordinate2D

NSDictionary *viewport = [[[results objectAtIndex:0] objectForKey:@"geometry"] 
                                                     objectForKey:@"viewport"];
NSDictionary *NEDictionary = [viewport objectForKey:@"northeast"];
NSDictionary *SWDictionary = [viewport objectForKey:@"southwest"];

CLLocationCoordinate2D SWCoordinate = 
    CLLocationCoordinate2DMake(
        [[SWDictionary objectForKey:@"lat"] floatValue], 
        [[SWDictionary objectForKey:@"lng"] floatValue]
    );
CLLocationCoordinate2D NECoordinate = 
    CLLocationCoordinate2DMake(
        [[NEDictionary objectForKey:@"lat"] floatValue], 
        [[NEDictionary objectForKey:@"lng"] floatValue]
    );    

我知道我需要从这些坐标生成 MKMapRect(或 MKMapRegion,以更容易的为准),然后 [mapView setVisibleRect:newRect animated:YES](或 [mapView setRegion:newRegion animated:YES] 但我不太确定如何到达那里。我需要一种将边界转换为正确数据结构的方法,例如:

- (MKMapRect) mapRectThatFitsBoundsSW:(CLLocationCoordinate2D)sw 
                                   NE:(CLLocationCoordinate2D)ne {
    // CGFloat x = ??
    // CGFloat y = ??
    // CGFloat width = ??
    // CGFloat height = ??
    MKMapRect mapRectFromBounds = MKMapRectMake(x,y,width,height);
    return mapRectFromBounds;
}

有什么想法吗?

【问题讨论】:

    标签: ios mkmapview mapkit


    【解决方案1】:

    有几种方法可以做到这一点。

    您可以通过找出center 点来创建MKCoordinateRegion,然后span 是角之间的绝对度数差。

    或者您可以使用 MapKit 函数 MKMapPointForCoordinate 创建一个 MKMapRect。要获得origin,请找出西北坐标并将其转换为MKMapPoint。要获取widthheight,请获取角之间ma​​ppoints 的绝对差异(首先使用函数将角从坐标转换为MKMapPoints)。

    另一种快速方法是使用MKMapRectUnion 函数的小技巧。从每个坐标创建一个大小为零的MKMapRect,然后使用以下函数将两个矩形合并为一个大矩形:

    MKMapPoint swPoint = MKMapPointForCoordinate(SWCoordinate);
    MKMapRect swRect = MKMapRectMake(swPoint.x, swPoint.y, 0, 0);
    
    MKMapPoint nePoint = MKMapPointForCoordinate(NECoordinate);
    MKMapRect neRect = MKMapRectMake(nePoint.x, nePoint.y, 0, 0);
    
    MKMapRect rect = MKMapRectUnion(swRect, neRect);
    

    请记住,地图视图仍会根据地图视图的比例和所需的缩放比例对您请求的矩形进行自己的调整。 (如果你想知道调整后的矩形是什么,请调用地图视图的mapRectThatFits: 方法。)

    【讨论】:

    • 这是一个非常巧妙的技巧。作为数学最少的人,应该得到更多的支持。
    【解决方案2】:

    如果您的边界可以跨越 180 度子午线,则必须在转换中考虑到这一点:

    - (MKMapRect) mapRectThatFitsBoundsSW:(CLLocationCoordinate2D)sw 
                                       NE:(CLLocationCoordinate2D)ne 
    {
        MKMapPoint pSW = MKMapPointForCoordinate(sw);
        MKMapPoint pNE = MKMapPointForCoordinate(ne);
    
        double antimeridianOveflow = 
          (ne.longitude > sw.longitude) ? 0 : MKMapSizeWorld.width;    
    
        return MKMapRectMake(pSW.x, pNE.y, 
                            (pNE.x - pSW.x) + antimeridianOveflow, 
                            (pSW.y - pNE.y));
    }
    

    但要小心那些跨越anitmeridianMKMapRects,因为它们来自龙居住的土地。如果您想了解其中的一些危险,请查看 MKMapRect and displaying map overlays that span 180th meridian。您已被警告!

    【讨论】:

      【解决方案3】:

      我发现了一些有用的东西。我最终选择了这个:

      - (MKMapRect) mapRectThatFitsBoundsSW:(CLLocationCoordinate2D)sw 
                                         NE:(CLLocationCoordinate2D)ne {
          MKMapPoint nePoint = MKMapPointForCoordinate(ne);
          MKMapPoint swPoint = MKMapPointForCoordinate(sw);
          CGFloat width = ABS(nePoint.x - swPoint.x);
          CGFloat height = ABS(nePoint.y - swPoint.y);
          MKMapRect newMapRect = MKMapRectMake(
              MIN(swPoint.x, nePoint.x), 
              MIN(swPoint.y, nePoint.y), 
              width, 
              height
          );
      
          // if (!MKMapRectSpans180thMeridian(newMapRect)) {
              return newMapRect;
          // } else {
              // ????
          // }
      }
      

      【讨论】:

      • 如果您确定 NE 和 SW 点是正确的(而不是交换为 NW 和 SE 或其他),那么您不需要 ABS。如果您不确定它们是否是正确的角,那么您需要将两个可能的 x 坐标中的最小值作为 MKMapRectMake 的第一个参数。对 y 也一样。当然,这一切都取决于你没有任何越过反子午线的盒子。
      • 我明白为什么不用担心哪个坐标是 NE 或 SW 会很好,以防万一它们意外交换,所以我将 MIN 添加到 MKMapRect x 和 y。逆经问题如何处理?
      • 由于 MKMapView 不会越过日期线,因此您也无法绘制越过日期线的框。要确定您给出的坐标是否真的越线,您要么需要确定哪个是 NE,哪个是 SW,然后检查 NE 是否实际上比 SW 更“西”(在 -180 和+180)如果是这样,那么盒子越过这条线。如果您不知道哪个坐标属于右上角/左下角,则获取它们的经度值的绝对差。 >180 意味着绕地球另一端转一圈会更短。
      • @jmcopeland 查看我对“我们如何处理反经络问题”的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-16
      • 2016-10-07
      • 2012-05-02
      • 1970-01-01
      • 1970-01-01
      • 2012-08-25
      相关资源
      最近更新 更多