Conversion MKCoordinateRegion en MKMapRect
j'ai un MKMapView carré dans mon application, et je souhaite mettre un point central et la hauteur exacte/largeur de la vue en mètres.
créer un MKCoordinateRegion et mettre la carte à elle (comme dans ce code...
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(center_coord, 1000.0, 1000.0);
[self.mapView setRegion:region animated:YES];
..) ne fonctionne pas correctement parce que l'utilisation de régions ici signifie simplement qu'au moins cette région est affichée, généralement plus que la région est.
Je suis à la planification sur l'utilisation de setVisibleMapRect: animated: méthode à la place, car je crois que cela va zoomer sur le réel MKMapRect passé.
alors, y a-t-il un moyen simple de convertir entre un MKcoordinateRegion et un MKMapRect? Peut-être obtenir les coordonnées haut-gauche et bas-droite de la région, et les utiliser pour faire le MKMapRect?
Je ne voyais rien de pratique sur la carte Fonctions Du Kit Référence .
(utilisant iOS 5, Xcode 4.2)
9 réponses
pour ajouter une autre implémentation à la pile:
- (MKMapRect)MKMapRectForCoordinateRegion:(MKCoordinateRegion)region
{
MKMapPoint a = MKMapPointForCoordinate(CLLocationCoordinate2DMake(
region.center.latitude + region.span.latitudeDelta / 2,
region.center.longitude - region.span.longitudeDelta / 2));
MKMapPoint b = MKMapPointForCoordinate(CLLocationCoordinate2DMake(
region.center.latitude - region.span.latitudeDelta / 2,
region.center.longitude + region.span.longitudeDelta / 2));
return MKMapRectMake(MIN(a.x,b.x), MIN(a.y,b.y), ABS(a.x-b.x), ABS(a.y-b.y));
}
NB: il y a plusieurs façons de convertir entre MKMapRect
et MKCoordinateRegion
. Celui-ci est certainement pas l'exact inverse de MKCoordinateRegionMakeWithDistance()
, mais se rapproche assez bien. Donc, faites attention à la conversion de va-et-vient, parce que l'information peut être perdue.
C'est une Swift version de Leo & Barnhart solution
func MKMapRectForCoordinateRegion(region:MKCoordinateRegion) -> MKMapRect {
let topLeft = CLLocationCoordinate2D(latitude: region.center.latitude + (region.span.latitudeDelta/2), longitude: region.center.longitude - (region.span.longitudeDelta/2))
let bottomRight = CLLocationCoordinate2D(latitude: region.center.latitude - (region.span.latitudeDelta/2), longitude: region.center.longitude + (region.span.longitudeDelta/2))
let a = MKMapPointForCoordinate(topLeft)
let b = MKMapPointForCoordinate(bottomRight)
return MKMapRect(origin: MKMapPoint(x:min(a.x,b.x), y:min(a.y,b.y)), size: MKMapSize(width: abs(a.x-b.x), height: abs(a.y-b.y)))
}
utilisez MKMapPointForCoordinate pour convertir les 2 points de la région (Haut / Gauche et bas / droite), puis créer le MKMapRect en utilisant les 2 MKMapPoints
CLLocationCoordinate2D coordinateOrigin = CLLocationCoordinate2DMake(latitude, longitude);
CLLocationCoordinate2D coordinateMax = CLLocationCoordinate2DMake(latitude + cellSize, longitude + cellSize);
MKMapPoint upperLeft = MKMapPointForCoordinate(coordinateOrigin);
MKMapPoint lowerRight = MKMapPointForCoordinate(coordinateMax);
MKMapRect mapRect = MKMapRectMake(upperLeft.x,
upperLeft.y,
lowerRight.x - upperLeft.x,
lowerRight.y - upperLeft.y);
vous pouvez utiliser la méthode pour convertir MKCoordinateRegion
en CGRect
- (CGRect)convertRegion:(MKCoordinateRegion)region toRectToView:(UIView *)view
et utiliser - (MKMapRect)mapRectForRect:(CGRect)rect
ou utiliser la méthode MKMapPointForCoordinate
pour convertir d'abord les coordonnées en MKPoint
et utiliser cette méthode pour former MKMapRect
pour éventuellement utiliser setVisibleMapRect:animated:
@Bogdan
je pense qu'il devrait être:
CLLocationCoordinate2D topLeftCoordinate =
CLLocationCoordinate2DMake(coordinateRegion.center.latitude
+ (coordinateRegion.span.latitudeDelta/2.0),
coordinateRegion.center.longitude
- (coordinateRegion.span.longitudeDelta/2.0));
MKMapPoint topLeftMapPoint = MKMapPointForCoordinate(topLeftCoordinate);
CLLocationCoordinate2D bottomRightCoordinate =
CLLocationCoordinate2DMake(coordinateRegion.center.latitude
- (coordinateRegion.span.latitudeDelta/2.0),
coordinateRegion.center.longitude
+ (coordinateRegion.span.longitudeDelta/2.0));
MKMapPoint bottomRightMapPoint = MKMapPointForCoordinate(bottomRightCoordinate);
MKMapRect mapRect = MKMapRectMake(topLeftMapPoint.x,
topLeftMapPoint.y,
fabs(bottomRightMapPoint.x-topLeftMapPoint.x),
fabs(bottomRightMapPoint.y-topLeftMapPoint.y));
Selon pomme d'api de référence , MKCoordinateRegion.centre représente le point central de la région; et MKCoordinateSpan.latitudeDelta représente la distance Nord-Sud (mesurée en degrés) à afficher sur la carte; MKCoordinateSpan.la longitude Elta représente la distance est-ouest (mesurée en degrés) à afficher pour la région cartographique.
@David réponse, en Swift 3
func mapRect(region: MKCoordinateRegion) -> MKMapRect {
let topLeft = CLLocationCoordinate2D(
latitude: region.center.latitude + (region.span.latitudeDelta/2.0),
longitude: region.center.longitude - (region.span.longitudeDelta/2.0)
)
let bottomRight = CLLocationCoordinate2D(
latitude: region.center.latitude - (region.span.latitudeDelta/2.0),
longitude: region.center.longitude + (region.span.longitudeDelta/2.0)
)
let topLeftMapPoint = MKMapPointForCoordinate(topLeft)
let bottomRightMapPoint = MKMapPointForCoordinate(bottomRight)
let origin = MKMapPoint(x: topLeftMapPoint.x,
y: topLeftMapPoint.y)
let size = MKMapSize(width: fabs(bottomRightMapPoint.x - topLeftMapPoint.x),
height: fabs(bottomRightMapPoint.y - topLeftMapPoint.y))
return MKMapRect(origin: origin, size: size)
}
la réponse donnée par @David (et par conséquent la version Swift 3 de @onmyway133) comporte une erreur importante chaque fois que la région traverse l'anti-méridien de l'hémisphère oriental (longitude 0 degrés à 180 degrés) à l'hémisphère occidental (longitude -180 degrés à 0 degrés). La largeur du MKMapRect sera plus grande qu'elle ne devrait l'être (habituellement beaucoup plus grand).
voici le correctif (pour le code Swift 3):
let topLeftMapPoint = MKMapPointForCoordinate(topLeft)
let bottomRightMapPoint = MKMapPointForCoordinate(bottomRight)
var width = bottomRightMapPoint.x - topLeftMapPoint.x
if width < 0.0 {
// Rect crosses from the Eastern Hemisphere to the Western Hemisphere
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)
prendre un MKCoordinateRegion, le convertir en MKMapRect avec le code ci-dessus, puis le retourner en MKCoordinateRegion en utilisant MKCoordinateRegionForMapRect() me donne un très bon accord entre la région d'entrée et la région de sortie partout sur la carte.
doit encore être un peu plus prudent sur la traversée du méridien (ainsi que l'enroulement autour des pôles) sinon MKMapPointForCoordinate retourne -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)
}
Certains cas de test de code (à l'aide d'Agile):
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)
}
utiliser la fonction intégrée MKCoordinateRegionForMapRect
MKCoordinateRegion region = MKCoordinateRegionForMapRect(rect);