我在Swift中编写应用程序,并使用Parse作为后端。
为了设置Parse的查询,我希望在当前的MKMapView上显示最西南的点和最东北的点。
我目前显示的是以下显示的值:
//___ To calculate the search bounds, first we need to calculate the corners of the map
let nePoint = CGPointMake(self.myMap.bounds.origin.x + myMap.bounds.size.width, myMap.bounds.origin.y);
let swPoint = CGPointMake((self.myMap.bounds.origin.x), (myMap.bounds.origin.y + myMap.bounds.size.height));
//___ Then transform those point into lat, lng values
let neCoord = myMap.convertPoint(nePoint, toCoordinateFromView: myMap)
let swCoord = myMap.convertPoint(swPoint, toCoordinateFromView: myMap)
let neGP = PFGeoPoint(latitude: neCoord.latitude, longitude: neCoord.longitude)
let swGP = PFGeoPoint(latitude: swCoord.latitude, longitude: swCoord.longitude)
var query = PFQuery(className: "locations")
//___ Limit what could be a lot of points.
query.limit = 25
query.whereKey("location", withinGeoBoxFromSouthwest: swGP, toNortheast: neGP)
这可以完美地工作,直到地图旋转。
但是,一旦用户旋转地图,右上角和左下角的点不再代表东北最多和最西南的点。
如何计算地图上显示的最西南部和东北部最正点?
感谢。
答案 0 :(得分:1)
对于我的应用程序,我必须得到一个完全包围可见地图区域的盒子的NE / SW角落。
要认识到的重要一点是,你不能通过仅仅采样两个角来找出旋转地图的边界坐标。
如果您只选择了此地图的右上角和左下角并转换为纬度/经度,您将获得红色矩形,这可能不是您想要的。
从图中可以看出,NE和SW边界点不在地图视图的任何位置。
相反,您需要对所有四个角进行采样,然后在比较它们之前将它们转换为纬度/经度,因为地图可能会颠倒旋转,这意味着您不知道哪个角更偏向北方/南方等等。
// Using http://stackoverflow.com/a/28683812/1207583 code extension name
typealias Edges = (ne: CLLocationCoordinate2D, sw: CLLocationCoordinate2D)
extension MKMapView {
func edgePoints() -> Edges {
let corners = [
CGPoint(x: self.bounds.minX, y: self.bounds.minY),
CGPoint(x: self.bounds.minX, y: self.bounds.maxY),
CGPoint(x: self.bounds.maxX, y: self.bounds.maxY),
CGPoint(x: self.bounds.maxX, y: self.bounds.minY)
]
let coords = corners.map { corner in
self.convertPoint(corner, toCoordinateFromView: self)
}
let startBounds = (
n: coords[0].latitude, s: coords[0].latitude,
e: coords[0].longitude, w: coords[0].longitude)
let bounds = coords.reduce(startBounds) { b, c in
let n = max(b.n, c.latitude)
let s = min(b.s, c.latitude)
let e = max(b.e, c.longitude)
let w = min(b.w, c.longitude)
return (n: n, s: s, e: e, w: w)
}
return (ne: CLLocationCoordinate2D(latitude: bounds.n, longitude: bounds.e),
sw: CLLocationCoordinate2D(latitude: bounds.s, longitude: bounds.w))
}
}
现在你运行时应该感到高兴
let edges = mapView.edgePoints()
debugPrint("Edges: ", edges)
答案 1 :(得分:0)
您需要围绕边界的中心旋转点
let degrees = 15 // rotation in degrees
// determine the center
let sw = swPoint
let ne = nePoint
let center = CGPoint(x: (ne.x-sw.x)/2+sw.x, y: (ne.y-sw.y)/2+sw.y)
let translate = CGAffineTransformMakeTranslation(-center.x, -center.y)
// Norm the points around the center
let swN = CGPointApplyAffineTransform(sw, translate)
let neN = CGPointApplyAffineTransform(ne, translate)
// Rotate your points around the center
let rotate = CGAffineTransformMakeRotation(CGFloat(degrees/180.0*M_PI))
let swR = CGPointApplyAffineTransform(swN, rotate)
let neR = CGPointApplyAffineTransform(neN, rotate)
// offset from the center back
let translateBack = CGAffineTransformMakeTranslation(center.x, center.y)
// Final coordinates
let newSouth = CGPointApplyAffineTransform(swR, translateBack)
let newNorth = CGPointApplyAffineTransform(neR, translateBack)
这有帮助吗?
要从地图返回坐标,请应用逆变换
编辑:修复最后一行的拼写错误
答案 2 :(得分:0)
MKMapView根据当前标题自动转换:
self.mapView.centerCoordinate = CLLocationCoordinate2D(latitude: 45.5249442, longitude: -73.59655650000002)
let pt0 = self.mapView.convertPoint(CGPointZero, toCoordinateFromView: self.mapView)
// pt0: latitude:80.777327154362311
// longitude:-163.59656124778414
self.mapView.camera.heading = 45.0
let pt1 = self.mapView.convertPoint(CGPointZero, toCoordinateFromView: self.mapView)
// pt1: latitude: -84.995143020120821
// longitude: -71.475233216395111
所以你实际上没有任何事情要做......
答案 3 :(得分:0)
我想出了一个(非常笨重的)解决方案。
这将显示地图视图中可见的实际最东北部和最西南部点,而不仅仅是围绕地图中心旋转点,这会导致点由于屏幕的矩形形状而移动到视图之外
let heading = myMap.camera.heading
let mapWidth = Double(myMap.frame.width)
let mapHeight = Double(myMap.frame.height)
var neX = mapWidth
var neY = 0.0
var swX = 0.0
var swY = mapHeight
if heading >= 0 && heading <= 90 {
let ratio = heading / 90
neX = (1 - ratio) * mapWidth
swX = mapWidth * ratio
} else if heading >= 90 && heading <= 180 {
let ratio = (heading - 90) / 90
neX = 0
neY = mapHeight * ratio
swY = (1 - ratio) * mapHeight
swX = mapWidth
} else if heading >= 180 && heading <= 270 {
let ratio = (heading - 180) / 90
neX = mapWidth * ratio
neY = mapHeight
swX = (1 - ratio) * mapWidth
swY = 0
} else if heading >= 270 && heading <= 360 {
let ratio = (heading - 270) / 90
neX = mapWidth
neY = (1 - ratio) * mapHeight
swY = ratio * mapHeight
}
let swPoint = CGPointMake(CGFloat(swX), CGFloat(swY))
let nePoint = CGPointMake(CGFloat(neX), CGFloat(neY))
let swCoord = myMap.convertPoint(swPoint, toCoordinateFromView: myMap)
let neCoord = myMap.convertPoint(nePoint, toCoordinateFromView: myMap)
//___ Then transform those point into lat,lng values
let swGP = PFGeoPoint(latitude: swCoord.latitude, longitude: swCoord.longitude)
let neGP = PFGeoPoint(latitude: neCoord.latitude, longitude: neCoord.longitude)
答案 4 :(得分:0)
Objective-C版本:
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];