旋转后在MKMapView上获取SW / NE点

时间:2015-03-04 19:23:04

标签: ios swift mkmapview

我在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)

这可以完美地工作,直到地图旋转。

但是,一旦用户旋转地图,右上角和左下角的点不再代表东北最多和最西南的点。

如何计算地图上显示的最西南部和东北部最正点?

感谢。

5 个答案:

答案 0 :(得分:1)

对于我的应用程序,我必须得到一个完全包围可见地图区域的盒子的NE / SW角落。

要认识到的重要一点是,你不能通过仅仅采样两个角来找出旋转地图的边界坐标。

如果您只选择了此地图的右上角和左下角并转换为纬度/经度,您将获得红色矩形,这可能不是您想要的。

Getting bounds of rotated map

从图中可以看出,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];