web-dev-qa-db-ja.com

MKMapViewの境界の取得

外部サーバーへのクエリを設定するために、作成中のiPhoneアプリで現在のマップビューの境界を取得したいと考えています。 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です。直接NSLogを実行しようとすると、self.mapView.bounds.size.widthによって「プログラム受信信号:「EXC_BAD_ACCESS」が表示されます。」 NSLogから来たようです。

MKMapViewの可視領域から南東コーナーと北西コーナー(マップ座標)を取得する適切な方法を知っている人はいますか?

編集:あなたがここで何かを尋ねたときはいつでも答えがすぐにあなたに来るようです。エラーをスローしていたNSLogの各変数を出力するために、@ fではなく%@を使用していました。 MKMapviewのannotationVisibleRectプロパティも発見しました。ただし、annotationVisibleRectは親ビューの座標に基づいているようです。

32
deadroxy

さて、私は自分の質問に正式に回答しましたが、ここに回答を投稿する前にどこにもそれが見つからなかったので:

//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];
75
deadroxy

別のオプションは、MKMapViewインスタンスのvisibleMapRectプロパティを使用し、MKCoordinateForMapPoint()を使用して緯度/経度に変換することです。

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);
41
afarnham

すぐに...(@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)
    }
}
9
Aviel Gross

これ http://wiki.openstreetmap.org/wiki/Bounding_Box はバウンディングボックスのドキュメントです

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

enter image description here

これを表す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,
    ]
  }
}

visibleMapRectregion.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)
6
onmyway133

この拡張機能はこの問題を解決し、centerCoordinate構文を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
    }
}
3
RodolfoAntonici

私の目的のために@ 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)
1

これを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];
1
Cindy

このウェブサイトは問題を解決します。 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]];
}
1
Zgpeace

2本の指で回転させたマップについて、他のいくつかの回答で問題が発生しました。このコードは私のために働きました:

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

私の答えは 陈保状の答え および関連するWebサイト ここにリンクの説明を入力 から派生しています。南西と北東のコーナーの3つのラインも簡略化しました。

0
Marc

このコードは、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];
0
Can Aksoy