为了设置外部服务器的查询,我想在我正在构建的iPhone应用程序中获取当前Map View的边界。 UIView应该响应边界,但似乎MKMapView没有。设置区域并放大地图后,我尝试获取边界。我坚持第一步,试图获得代表地图SE和NW角落的CGPoints。之后我打算用:
- (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(UIView *)view
将点转换为地图坐标。但我甚至无法做到那么远......
//Recenter and zoom map in on search location
MKCoordinateRegion region = {{0.0f, 0.0f}, {0.0f, 0.0f}};
region.center = mySearchLocation.searchLocation.coordinate;
region.span.longitudeDelta = 0.01f;
region.span.latitudeDelta = 0.01f;
[self.mapView setRegion:region animated:YES];
//After the new search location has been added to the map, and the map zoomed, we need to update the search bounds
//First we need to calculate the corners of the map
CGPoint se = CGPointMake(self.mapView.bounds.origin.x, mapView.bounds.origin.y);
CGPoint nw = CGPointMake((self.mapView.bounds.origin.x + mapView.bounds.size.width), (mapView.bounds.origin.y + mapView.bounds.size.height));
NSLog(@"points are: se %@, nw %@", se, nw);
代码编译时没有警告,但se和nw都是null。查看self.mapView.bounds.origin.x变量为0.尝试直接使用NS.LogView.bounds.size.width给我一个“程序接收信号:”EXC_BAD_ACCESS“。”这似乎来自NSLog。
有人知道从MKMapView的可见区域获取东南角和西北角(在地图坐标中)的正确方法吗?
编辑:似乎每当你在这里问一些问题时,答案就会立刻传到你身上。我使用%@而不是@f来打印NSLog中的每个变量,这些变量在那里抛出错误。我还发现了MKMapview的annotationVisibleRect属性。虽然annotationVisibleRect似乎是基于父视图坐标。
好吧,我正式回答了我自己的问题,但由于我没有在任何地方找到它,我会在这里发布答案:
//To calculate the search bounds...
//First we need to calculate the corners of the map so we get the points
CGPoint nePoint = CGPointMake(self.mapView.bounds.origin.x + mapView.bounds.size.width, mapView.bounds.origin.y);
CGPoint swPoint = CGPointMake((self.mapView.bounds.origin.x), (mapView.bounds.origin.y + mapView.bounds.size.height));
//Then transform those point into lat,lng values
CLLocationCoordinate2D neCoord;
neCoord = [mapView convertPoint:nePoint toCoordinateFromView:mapView];
CLLocationCoordinate2D swCoord;
swCoord = [mapView convertPoint:swPoint toCoordinateFromView:mapView];
为了我的目的更新了@ onmyway133的优秀答案,我需要所有四个角的坐标:
struct BoundingBox {
let topRight: CLLocationCoordinate2D
let topLeft: CLLocationCoordinate2D
let bottomRight: CLLocationCoordinate2D
let bottomLeft: CLLocationCoordinate2D
init(rect: MKMapRect) {
topRight = MKMapPoint(x: rect.maxX, y: rect.origin.y).coordinate
topLeft = MKMapPoint(x: rect.origin.x, y: rect.origin.y).coordinate
bottomRight = MKMapPoint(x: rect.maxX, y: rect.maxY).coordinate
bottomLeft = MKMapPoint(x: rect.origin.x, y: rect.maxY).coordinate
}
var items: [String: CLLocationCoordinate2D] {
return [
"topRight": topRight,
"topLeft": topLeft,
"bottomRight": bottomRight,
"bottomLeft": bottomLeft,
]
}
var points: [CLLocationDegrees] {
return [
topRight.latitude,
topRight.longitude,
topLeft.latitude,
topLeft.longitude,
bottomRight.latitude,
bottomRight.longitude,
bottomLeft.latitude,
bottomLeft.longitude,
]
}
}
以及我如何使用这些数据的示例:
let boundingBox = BoundingBox(rect: mapView.visibleMapRect)
var annotations = Array<MKPointAnnotation>()
for point in boundingBox.items {
let newPoint = MKPointAnnotation()
newPoint.coordinate = point.value
annotations.append(newPoint)
}
mapView.addAnnotations(annotations)
另一种选择是在MKMapView实例上使用visibleMapRect属性,并使用MKCoordinateForMapPoint()转换为lat / lon。
MKMapRect mRect = self.mapView.visibleMapRect;
MKMapPoint neMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), mRect.origin.y);
MKMapPoint swMapPoint = MKMapPointMake(mRect.origin.x, MKMapRectGetMaxY(mRect));
CLLocationCoordinate2D neCoord = MKCoordinateForMapPoint(neMapPoint);
CLLocationCoordinate2D swCoord = MKCoordinateForMapPoint(swMapPoint);
迅速离开...(根据@ deadroxy的回答...)
typealias Edges = (ne: CLLocationCoordinate2D, sw: CLLocationCoordinate2D)
extension MKMapView {
func edgePoints() -> Edges {
let nePoint = CGPoint(x: self.bounds.maxX, y: self.bounds.origin.y)
let swPoint = CGPoint(x: self.bounds.minX, y: self.bounds.maxY)
let neCoord = self.convertPoint(nePoint, toCoordinateFromView: self)
let swCoord = self.convertPoint(swPoint, toCoordinateFromView: self)
return (ne: neCoord, sw: swCoord)
}
}
这个http://wiki.openstreetmap.org/wiki/Bounding_Box是一个边界框文件
bbox = left,bottom,right,top
bbox = min Longitude , min Latitude , max Longitude , max Latitude
你可以有一个代表这个的BoundingBox
结构
struct BoundingBox {
let min: CLLocationCoordinate2D
let max: CLLocationCoordinate2D
init(rect: MKMapRect) {
let bottomLeft = MKMapPointMake(rect.origin.x, MKMapRectGetMaxY(rect))
let topRight = MKMapPointMake(MKMapRectGetMaxX(rect), rect.origin.y)
min = MKCoordinateForMapPoint(bottomLeft)
max = MKCoordinateForMapPoint(topRight)
}
var points: [CLLocationDegrees] {
return [
min.latitude,
min.longitude,
max.latitude
max.longitude,
]
}
}
visibleMapRect
与region.span
相同
let mapView = MKMapView(frame: CGRect(x: 0, y: 0, width: 320, height: 640))
XCTAssertEqual(mapView.userLocation.coordinate.latitude, 0)
XCTAssertEqual(mapView.userLocation.coordinate.longitude, 0)
let boundingBox = BoundingBox(rect: mapView.visibleMapRect)
XCTAssertEqual(boundingBox.max.longitude-boundingBox.min.longitude, mapView.region.span.longitudeDelta)
XCTAssertEqual(boundingBox.max.latitude-boundingBox.min.latitude, mapView.region.span.latitudeDelta)
我能够使用Parse GeoBox查询:
//Calculate the corners of the map to get the points
CGPoint nePoint = CGPointMake(self.mapView.bounds.origin.x + self.mapView.bounds.size.width, self.mapView.bounds.origin.y);
CGPoint swPoint = CGPointMake((self.mapView.bounds.origin.x),(self.mapView.bounds.origin.y+ self.mapView.bounds.size.height));
//Transform points into lat/long values
CLLocationCoordinate2D NECoordinate = [self.mapView convertPoint:nePoint toCoordinateFromView:self.mapView];
CLLocationCoordinate2D SWCoordinate = [self.mapView convertPoint:swPoint toCoordinateFromView:self.mapView];
//Convert to Parse GeoPoints
PFGeoPoint *Southwest = [PFGeoPoint geoPointWithLatitude:SWCoordinate.latitude longitude:SWCoordinate.longitude];
PFGeoPoint *Northeast = [PFGeoPoint geoPointWithLatitude:NECoordinate.latitude longitude:NECoordinate.longitude];
这个网站解决了这个问题。 http://www.softwarepassion.com/how-to-get-geographic-coordinates-of-the-visible-mkmapview-area-in-ios/
MKMapRect mRect = self.mapView.visibleMapRect;
-(CLLocationCoordinate2D)getNECoordinate:(MKMapRect)mRect{
return [self getCoordinateFromMapRectanglePoint:MKMapRectGetMaxX(mRect) y:mRect.origin.y];
}
-(CLLocationCoordinate2D)getNWCoordinate:(MKMapRect)mRect{
return [self getCoordinateFromMapRectanglePoint:MKMapRectGetMinX(mRect) y:mRect.origin.y];
}
-(CLLocationCoordinate2D)getSECoordinate:(MKMapRect)mRect{
return [self getCoordinateFromMapRectanglePoint:MKMapRectGetMaxX(mRect) y:MKMapRectGetMaxY(mRect)];
}
-(CLLocationCoordinate2D)getSWCoordinate:(MKMapRect)mRect{
return [self getCoordinateFromMapRectanglePoint:mRect.origin.x y:MKMapRectGetMaxY(mRect)];
}
-(CLLocationCoordinate2D)getCoordinateFromMapRectanglePoint:(double)x y:(double)y{
MKMapPoint swMapPoint = MKMapPointMake(x, y);
return MKCoordinateForMapPoint(swMapPoint);
}
-(NSArray *)getBoundingBox:(MKMapRect)mRect{
CLLocationCoordinate2D bottomLeft = [self getSWCoordinate:mRect];
CLLocationCoordinate2D topRight = [self getNECoordinate:mRect];
return @[[NSNumber numberWithDouble:bottomLeft.latitude ],
[NSNumber numberWithDouble:bottomLeft.longitude],
[NSNumber numberWithDouble:topRight.latitude],
[NSNumber numberWithDouble:topRight.longitude]];
}
此扩展解决了此问题并在Swift 5中维护centerCoordinate
语法
extension MKMapView {
var northWestCoordinate: CLLocationCoordinate2D {
return MKMapPoint(x: visibleMapRect.minX, y: visibleMapRect.minY).coordinate
}
var northEastCoordinate: CLLocationCoordinate2D {
return MKMapPoint(x: visibleMapRect.maxX, y: visibleMapRect.minY).coordinate
}
var southEastCoordinate: CLLocationCoordinate2D {
return MKMapPoint(x: visibleMapRect.maxX, y: visibleMapRect.maxY).coordinate
}
var southWestCoordinate: CLLocationCoordinate2D {
return MKMapPoint(x: visibleMapRect.minX, y: visibleMapRect.maxY).coordinate
}
}
此代码适用于像90/180度旋转的地图。 set mapView.pitchEnabled = NO;减少错误。
CLLocationDirection heading = mapView.camera.heading;
float mapWidth = mapView.frame.size.width;
float mapHeight = mapView.frame.size.height;
float neX = mapWidth;
float neY = 0.0;
float swX = 0.0;
float swY = mapHeight;
if (heading >= 0 && heading <= 90) {
//println("Q1")
float ratio = heading / 90;
neX = (1-ratio) * mapWidth;
swX = (mapWidth*ratio);
} else if (heading >= 90 && heading <= 180) {
//println("Q2")
float ratio = (heading - 90) / 90;
neX = 0;
neY = (mapHeight*ratio);
swY = (1-ratio) * mapHeight;
swX = mapWidth;
} else if (heading >= 180 && heading <= 270) {
//println("Q3")
float ratio = (heading - 180) / 90;
neX = mapWidth*ratio;
neY = mapHeight;
swX = (1-ratio) * mapWidth;
swY = 0;
} else if (heading >= 270 && heading <= 360) {
//println("Q4");
float ratio = (heading - 270) / 90;
neX = mapWidth;
neY = (1-ratio) * mapHeight;
swY = ratio * mapHeight;
}
CGPoint swPoint = CGPointMake(swX, swY);
CGPoint nePoint = CGPointMake(neX, neY);
CLLocationCoordinate2D swCoord = [mapView convertPoint:swPoint toCoordinateFromView:mapView];
CLLocationCoordinate2D neCoord = [mapView convertPoint:nePoint toCoordinateFromView:mapView];
对于已经旋转了2个手指的地图,我遇到了一些其他答案的问题。这段代码对我有用:
MKMapRect rect = self.mapView.visibleMapRect;
CLLocationCoordinate2D northeast = MKCoordinateForMapPoint(MKMapPointMake(MKMapRectGetMaxX(rect),rect.origin.y));
CLLocationCoordinate2D southwest = MKCoordinateForMapPoint(MKMapPointMake(rect.origin.x ,MKMapRectGetMaxY(rect)));
我的答案来自陈保状's answer和相关网站enter link description here。它简化了西南和东北角的3条线。