将MKCoordinateRegion转换为MKMapRect

我在我的应用程序中有一个正方形的MKMapView,我希望以米为单位设置中心点和视图的确切高度/宽度。

创build一个MKCoordinateRegion并设置地图(如在这个代码中…

MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(center_coord, 1000.0, 1000.0); [self.mapView setRegion:region animated:YES]; 

..)不能正常工作,因为在这里使用区域意味着至less显示该区域,通常比区域更多。

我打算使用setVisibleMapRect:animated:方法,因为我相信这将缩放到实际传递的MKMapRect 。

那么,是否有一个简单的方法来在MKcoordinateRegion和MKMapRect之间进行转换? 也许获取该区域的左上angular和右下angular坐标,并使用它们来使MKMapRect?

我在Map工具包函数参考中看不到任何东西。

(使用iOS 5,Xcode 4.2)

要添加另一个实现:

 - (MKMapRect)MKMapRectForCoordinateRegion:(MKCoordinateRegion)region { MKMapPoint a = MKMapPointForCoordinate(CLLocationCoordinate2DMake( region.center.latitude + region.span.latitudeDelta / 2, region.center.longitude - region.span.longitudeDelta / 2)); MKMapPoint b = MKMapPointForCoordinate(CLLocationCoordinate2DMake( region.center.latitude - region.span.latitudeDelta / 2, region.center.longitude + region.span.longitudeDelta / 2)); return MKMapRectMake(MIN(ax,bx), MIN(ay,by), ABS(ax-bx), ABS(ay-by)); } 

注意:在MKMapRectMKCoordinateRegion之间转换有很多种方法。 这当然不是 MKCoordinateRegionMakeWithDistance()的精确倒数,但近似相当好。 所以,小心转换,因为信息可能会丢失。

这是Leo&Barnhart解决scheme的Swift版本

 func MKMapRectForCoordinateRegion(region:MKCoordinateRegion) -> MKMapRect { let topLeft = CLLocationCoordinate2D(latitude: region.center.latitude + (region.span.latitudeDelta/2), longitude: region.center.longitude - (region.span.longitudeDelta/2)) let bottomRight = CLLocationCoordinate2D(latitude: region.center.latitude - (region.span.latitudeDelta/2), longitude: region.center.longitude + (region.span.longitudeDelta/2)) let a = MKMapPointForCoordinate(topLeft) let b = MKMapPointForCoordinate(bottomRight) return MKMapRect(origin: MKMapPoint(x:min(ax,bx), y:min(ay,by)), size: MKMapSize(width: abs(ax-bx), height: abs(ay-by))) } 

使用MKMapPointForCoordinate转换区域的2个点(上/左和下/右),然后使用2个MKMapPoints创buildMKMapRect

  CLLocationCoordinate2D coordinateOrigin = CLLocationCoordinate2DMake(latitude, longitude); CLLocationCoordinate2D coordinateMax = CLLocationCoordinate2DMake(latitude + cellSize, longitude + cellSize); MKMapPoint upperLeft = MKMapPointForCoordinate(coordinateOrigin); MKMapPoint lowerRight = MKMapPointForCoordinate(coordinateMax); MKMapRect mapRect = MKMapRectMake(upperLeft.x, upperLeft.y, lowerRight.x - upperLeft.x, lowerRight.y - upperLeft.y); 

您可以使用方法将MKCoordinateRegion转换为CGRect

 - (CGRect)convertRegion:(MKCoordinateRegion)region toRectToView:(UIView *)view 

并使用- (MKMapRect)mapRectForRect:(CGRect)rect

或者使用MKMapPointForCoordinate方法首先将坐标转换为MKPoint并使用它来形成MKMapRect最终使用setVisibleMapRect:animated:

@Bogdan

我认为这应该是:

  CLLocationCoordinate2D topLeftCoordinate = CLLocationCoordinate2DMake(coordinateRegion.center.latitude + (coordinateRegion.span.latitudeDelta/2.0), coordinateRegion.center.longitude - (coordinateRegion.span.longitudeDelta/2.0)); MKMapPoint topLeftMapPoint = MKMapPointForCoordinate(topLeftCoordinate); CLLocationCoordinate2D bottomRightCoordinate = CLLocationCoordinate2DMake(coordinateRegion.center.latitude - (coordinateRegion.span.latitudeDelta/2.0), coordinateRegion.center.longitude + (coordinateRegion.span.longitudeDelta/2.0)); MKMapPoint bottomRightMapPoint = MKMapPointForCoordinate(bottomRightCoordinate); MKMapRect mapRect = MKMapRectMake(topLeftMapPoint.x, topLeftMapPoint.y, fabs(bottomRightMapPoint.x-topLeftMapPoint.x), fabs(bottomRightMapPoint.y-topLeftMapPoint.y)); 

根据苹果API参考 ,MKCoordinateRegion.center代表该地区的中心点; MKCoordinateSpan.latitudeDelta表示要在地图上显示的北向南距离(以度为单位)的量; MKCoordinateSpan.longitudeDelta表示要显示的地图区域的东西距离(以度为单位)。

使用内置函数MKCoordinateRegionForMapRect

 MKCoordinateRegion region = MKCoordinateRegionForMapRect(rect); 

当大卫从东半球(经度0度到180度)越过反经线到西半球(经度-180度)时,答案@David给出了(因此@ onmyway133上的Swift 3版本)到0度)。 MKMapRect的宽度将比它应该更大(通常大得多)。

这里是修复(对于Swift 3代码):

 let topLeftMapPoint = MKMapPointForCoordinate(topLeft) let bottomRightMapPoint = MKMapPointForCoordinate(bottomRight) var width = bottomRightMapPoint.x - topLeftMapPoint.x if width < 0.0 { // Rect crosses from the Eastern Hemisphere to the Western Hemisphere width += MKMapPointForCoordinate(CLLocationCoordinate2D(latitude: 0.0, longitude: 180.0)).x } let height = bottomRightMapPoint.y - topLeftMapPoint.y let size = MKMapSize(width: width, height: height) return MKMapRect(origin: topLeftMapPoint, size: size) 

取一个MKCoordinateRegion,用上面的代码把它转换成一个MKMapRect,然后使用MKCoordinateRegionForMapRect()把它转换回MKCoordinateRegion,这使得我在input区域和输出区域之间在地图上的任何地方都有非常好的一致性。

@大卫的答案,在斯威夫特3

 func mapRect(region: MKCoordinateRegion) -> MKMapRect { let topLeft = CLLocationCoordinate2D( latitude: region.center.latitude + (region.span.latitudeDelta/2.0), longitude: region.center.longitude - (region.span.longitudeDelta/2.0) ) let bottomRight = CLLocationCoordinate2D( latitude: region.center.latitude - (region.span.latitudeDelta/2.0), longitude: region.center.longitude + (region.span.longitudeDelta/2.0) ) let topLeftMapPoint = MKMapPointForCoordinate(topLeft) let bottomRightMapPoint = MKMapPointForCoordinate(bottomRight) let origin = MKMapPoint(x: topLeftMapPoint.x, y: topLeftMapPoint.y) let size = MKMapSize(width: fabs(bottomRightMapPoint.x - topLeftMapPoint.x), height: fabs(bottomRightMapPoint.y - topLeftMapPoint.y)) return MKMapRect(origin: origin, size: size) } 

仍然必须更仔细地穿越子午线(以及围绕两极),否则MKMapPointForCoordinate返回-1,-1:

 public func MKMapRectForCoordinateRegion(region:MKCoordinateRegion) -> MKMapRect { var topLeft = CLLocationCoordinate2D( latitude: min(region.center.latitude + (region.span.latitudeDelta/2.0), 90), longitude: region.center.longitude - (region.span.longitudeDelta/2.0) ) if topLeft.longitude < -180 { // We wrapped around the meridian topLeft.longitude += 360 } var bottomRight = CLLocationCoordinate2D( latitude: max(region.center.latitude - (region.span.latitudeDelta/2.0), -90), longitude: region.center.longitude + (region.span.longitudeDelta/2.0) ) if bottomRight.longitude > 180 { // We wrapped around the medridian bottomRight.longitude -= 360 } let topLeftMapPoint = MKMapPointForCoordinate(topLeft) let bottomRightMapPoint = MKMapPointForCoordinate(bottomRight) var width = bottomRightMapPoint.x - topLeftMapPoint.x if width < 0.0 { // Rect crosses meridian width += MKMapPointForCoordinate(CLLocationCoordinate2D(latitude: 0.0, longitude: 180.0)).x } let height = bottomRightMapPoint.y - topLeftMapPoint.y let size = MKMapSize(width: width, height: height) return MKMapRect(origin: topLeftMapPoint, size: size) } 

一些testing用例代码(使用Nimble):

 func testMKMapRectForCoordinateRegion() { let northWesternRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(45.0, -90.0), MKCoordinateSpanMake(20.0, 20.0)) let northWesternMapRect = MKMapRectForCoordinateRegion(region: northWesternRegion) let convertedNWRegion = MKCoordinateRegionForMapRect(northWesternMapRect) expect(self.equivalentRegions(northWesternRegion, convertedNWRegion)).to(beTrue()) let northEasternRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(45.0, 90.0), MKCoordinateSpanMake(20.0, 20.0)) let northEasternMapRect = MKMapRectForCoordinateRegion(region: northEasternRegion) let convertedNERegion = MKCoordinateRegionForMapRect(northEasternMapRect) expect(self.equivalentRegions(northEasternRegion, convertedNERegion)).to(beTrue()) let southWesternRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(-45.0, -90.0), MKCoordinateSpanMake(20.0, 20.0)) let southWesternMapRect = MKMapRectForCoordinateRegion(region: southWesternRegion) let convertedSWRegion = MKCoordinateRegionForMapRect(southWesternMapRect) expect(self.equivalentRegions(southWesternRegion, convertedSWRegion)).to(beTrue()) let southEasternRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(-45.0, 90.0), MKCoordinateSpanMake(20.0, 20.0)) let southEasternMapRect = MKMapRectForCoordinateRegion(region: southEasternRegion) let convertedSERegion = MKCoordinateRegionForMapRect(southEasternMapRect) expect(self.equivalentRegions(southEasternRegion, convertedSERegion)).to(beTrue()) let meridianSpanEastRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(0.0, 170.0), MKCoordinateSpanMake(20.0, 20.0)) let meridianSpanEastMapRect = MKMapRectForCoordinateRegion(region: meridianSpanEastRegion) let convertedMeridianSpanEastRegion = MKCoordinateRegionForMapRect(meridianSpanEastMapRect) expect(self.equivalentRegions(meridianSpanEastRegion, convertedMeridianSpanEastRegion)).to(beTrue()) let meridianSpanWestRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(0.0, -170.0), MKCoordinateSpanMake(20.0, 20.0)) let meridianSpanWestMapRect = MKMapRectForCoordinateRegion(region: meridianSpanWestRegion) let convertedMeridianSpanWestRegion = MKCoordinateRegionForMapRect(meridianSpanWestMapRect) expect(self.equivalentRegions(meridianSpanWestRegion, convertedMeridianSpanWestRegion)).to(beTrue()) } fileprivate func equivalentRegions(_ regionA: MKCoordinateRegion, _ regionB: MKCoordinateRegion) -> Bool { // Allow a small delta between values let deltaAllowed: Double = 1.0 return (fabs(regionA.center.latitude - regionB.center.latitude) < deltaAllowed) && (fabs(regionA.center.longitude - regionB.center.longitude) < deltaAllowed) && (fabs(regionA.span.latitudeDelta - regionB.span.latitudeDelta) < deltaAllowed) && (fabs(regionA.span.longitudeDelta - regionB.span.longitudeDelta) < deltaAllowed) }