如何将由NE和SW坐标组成的特定边界拟合到可见地图视图中?

时间:2011-12-13 21:39:54

标签: ios mkmapview mapkit

我需要在地图中适应某些边界。我通过调用谷歌地理编码器并阅读视口属性来获得界限:

{
    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;
}

有什么想法吗?

3 个答案:

答案 0 :(得分:10)

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

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

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

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

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:方法。)

答案 1 :(得分: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));
}

但要注意那些跨越anitmeridianMKMapRect,因为它们来自龙所居住的土地。如果你想了解那里的一些危险,请看看 MKMapRect and displaying map overlays that span 180th meridian。你被警告了!

答案 2 :(得分:0)

我找到了有用的东西。我结束了这个:

- (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 {
        // ????
    // }
}