Getting the bounds of an MKMapView

前端 未结 10 946
既然无缘
既然无缘 2020-11-28 20:28

In order to setup a query to an external server I want to get the bounds of the current Map View in an iPhone app I\'m building. UIView should respond to bounds but it seems

相关标签:
10条回答
  • 2020-11-28 20:38

    This extension solves this problem and maintain the centerCoordinate syntax in Swift 5

    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
        }
    }
    
    0 讨论(0)
  • 2020-11-28 20:42

    This http://wiki.openstreetmap.org/wiki/Bounding_Box is a document for bounding box

    bbox = left,bottom,right,top
    bbox = min Longitude , min Latitude , max Longitude , max Latitude
    

    You can have a BoundingBox struct that represents this

    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,
        ]
      }
    }
    

    The visibleMapRect is the same as 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)
    
    0 讨论(0)
  • 2020-11-28 20:42

    I was having some trouble with some of the other answers for maps that had been 2 finger rotated. This code worked for me:

    MKMapRect rect = self.mapView.visibleMapRect;
    CLLocationCoordinate2D northeast = MKCoordinateForMapPoint(MKMapPointMake(MKMapRectGetMaxX(rect),rect.origin.y));
    CLLocationCoordinate2D southwest = MKCoordinateForMapPoint(MKMapPointMake(rect.origin.x         ,MKMapRectGetMaxY(rect)));
    

    My answer is derived from 陈保状's answer and the associated website enter link description here. Its simplified down too 3 lines for south west and north east corners.

    0 讨论(0)
  • 2020-11-28 20:43

    Updated @onmyway133's excellent answer for my purposes, I needed the coordinates of all four corners:

    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,
            ]
        }
    }
    

    And an example of how I used this data:

    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)
    
    0 讨论(0)
  • 2020-11-28 20:47

    Swift away... (Based on @deadroxy's answer...)

    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.convert(nePoint, toCoordinateFrom: self)
        let swCoord = self.convert(swPoint, toCoordinateFrom: self)
        
        return (ne: neCoord, sw: swCoord)
        }
    }
    
    0 讨论(0)
  • 2020-11-28 20:47

    This code works with map rotating like 90/180 degrees. set mapView.pitchEnabled = NO; for less bugs.

    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];
    
    0 讨论(0)
提交回复
热议问题