ios 将 MKCoordinateRegion 转换为 MKMapRect
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9270268/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert MKCoordinateRegion to MKMapRect
提问by Jon Cox
I have a square MKMapView in my app, and I wish to set a center point and the exact height/width of the view in meters.
我的应用程序中有一个方形 MKMapView,我希望设置一个中心点和视图的确切高度/宽度(以米为单位)。
Creating an MKCoordinateRegion and setting the map to it (as in this code...
创建一个 MKCoordinateRegion 并将地图设置为它(如在此代码中...
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(center_coord, 1000.0, 1000.0);
[self.mapView setRegion:region animated:YES];
..) doesn't work properly because using regions here just means that at least that region is displayed, typically more than the region is.
..) 无法正常工作,因为在此处使用区域仅意味着至少显示该区域,通常比该区域更多。
I'm planning on using setVisibleMapRect:animated:method instead, as I believe this will zoom to the actual MKMapRectpassed.
我打算改用setVisibleMapRect:animated:方法,因为我相信这会放大到实际传递的MKMapRect。
So, is there a simple way to convert between an MKcoordinateRegion and an MKMapRect? Perhaps getting the top-left and bottom-right coordinates of the region, and using them to the make the MKMapRect?
那么,是否有一种简单的方法可以在 MKcoordinateRegion 和 MKMapRect 之间进行转换?也许获取区域的左上角和右下角坐标,并使用它们来制作 MKMapRect?
I couldn't see anything handy in the Map Kit Functions Reference.
我在Map Kit Functions Reference中看不到任何有用的东西。
(Using iOS 5, Xcode 4.2)
(使用 iOS 5、Xcode 4.2)
回答by leo
To add another implementation to the pile:
向堆中添加另一个实现:
- (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(a.x,b.x), MIN(a.y,b.y), ABS(a.x-b.x), ABS(a.y-b.y));
}
NB: There are many ways to convert between MKMapRect
and MKCoordinateRegion
. This one certainly is notthe exact inverse of MKCoordinateRegionMakeWithDistance()
, but approximates it fairly well. So, be careful converting back and forth, because information can be lost.
注意:有很多方法可以在MKMapRect
和之间转换MKCoordinateRegion
。这当然不是的精确倒数MKCoordinateRegionMakeWithDistance()
,但相当接近它。因此,来回转换要小心,因为信息可能会丢失。
回答by Mike
This is a Swift verion to Leo & Barnhart solution
这是 Leo & Barnhart 解决方案的 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(a.x,b.x), y:min(a.y,b.y)), size: MKMapSize(width: abs(a.x-b.x), height: abs(a.y-b.y)))
}
回答by Bogdan
Use MKMapPointForCoordinate to convert the 2 point of the region (top/left and bottom/right), then create the MKMapRect using the 2 MKMapPoints
使用 MKMapPointForCoordinate 转换区域的 2 点(上/左和下/右),然后使用 2 MKMapPoints 创建 MKMapRect
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);
回答by chatur
you can use method to convert MKCoordinateRegion
to CGRect
您可以使用方法转换MKCoordinateRegion
为CGRect
- (CGRect)convertRegion:(MKCoordinateRegion)region toRectToView:(UIView *)view
and use - (MKMapRect)mapRectForRect:(CGRect)rect
并使用 - (MKMapRect)mapRectForRect:(CGRect)rect
or use MKMapPointForCoordinate
method to first convert coordinates to MKPoint
and use that to form MKMapRect
to eventually use setVisibleMapRect:animated:
或使用MKMapPointForCoordinate
方法首先将坐标转换为MKPoint
并使用它来形成MKMapRect
最终使用setVisibleMapRect:animated:
回答by David
@Bogdan
@博格丹
I think it should be:
我觉得应该是:
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));
According to apple api reference, MKCoordinateRegion.center represents the center point of the region; and MKCoordinateSpan.latitudeDelta represents the amount of north-to-south distance (measured in degrees) to display on the map; MKCoordinateSpan.longitudeDelta represents amount of east-to-west distance (measured in degrees) to display for the map region.
根据apple api reference,MKCoordinateRegion.center 代表区域的中心点;MKCoordinateSpan.latitudeDelta 表示地图上显示的南北距离(以度为单位);MKCoordinateSpan.longitudeDelta 表示要为地图区域显示的东西向距离(以度为单位)的量。
回答by onmyway133
@David's answer, in Swift 3
@David 的回答,在 Swift 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)
}
回答by Mark A Durham
The answer @David gave (and consequently the Swift 3 version by @onmyway133) has a significant error whenever the region crosses over the anti-meridian from the Eastern Hemisphere (longitude 0 degrees to 180 degrees) to the Western Hemisphere (longitude -180 degrees to 0 degrees). The width of the MKMapRect will be bigger than it should be (usually muchbigger).
每当该地区从东半球(经度 0 度到 180 度)到西半球(经度 -180 度)跨越反子午线时,@David 给出的答案(以及 @onmyway133 的 Swift 3 版本)都会出现重大错误到 0 度)。MKMapRect 的宽度将比它应该的要大(通常要大得多)。
Here is the fix (for the Swift 3 code):
这是修复(针对 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)
Taking an MKCoordinateRegion, converting it into an MKMapRect with the code above, and then turning it back into an MKCoordinateRegion using MKCoordinateRegionForMapRect() gives me very good agreement between the input region and the output region everywhere on the map.
取一个 MKCoordinateRegion,使用上面的代码将其转换为 MKMapRect,然后使用 MKCoordinateRegionForMapRect() 将其转换回 MKCoordinateRegion,这让我在地图上的输入区域和输出区域之间取得了很好的一致性。
回答by GilroyKilroy
Still have to be a bit more careful about crossing the meridian (as well as wrapping around the poles) otherwise MKMapPointForCoordinate returns -1, -1:
在穿越子午线(以及环绕极点)时仍然需要更加小心,否则 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)
}
Some test case code (using Nimble):
一些测试用例代码(使用 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)
}
回答by Duane Fields
Use the built in function MKCoordinateRegionForMapRect
使用内置函数 MKCoordinateRegionForMapRect
MKCoordinateRegion region = MKCoordinateRegionForMapRect(rect);