Convert MKCoordinateRegion to MKMapRect

前端 未结 10 656
南笙
南笙 2020-12-02 10:52

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.

Creating an MKCoordinateRegion and setting th

10条回答
  •  北海茫月
    2020-12-02 11:20

    Still have to be a bit more careful about crossing the meridian (as well as wrapping around the poles) otherwise MKMapPointForCoordinate returns -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):

    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)
    }
    

提交回复
热议问题