Reputation: 1617
Is there any way to get center coordinate of a set of CLLocationsCoordinate2D in iOS?
Upvotes: 8
Views: 10846
Reputation: 3418
A small Array extension with no magic numbers like -200.0
extension Array where Element == CLLocationCoordinate2D {
func center() -> CLLocationCoordinate2D {
var maxLatitude: Double = -.greatestFiniteMagnitude
var maxLongitude: Double = -.greatestFiniteMagnitude
var minLatitude: Double = .greatestFiniteMagnitude
var minLongitude: Double = .greatestFiniteMagnitude
for location in self {
maxLatitude = Swift.max(maxLatitude, location.latitude)
maxLongitude = Swift.max(maxLongitude, location.longitude)
minLatitude = Swift.min(minLatitude, location.latitude)
minLongitude = Swift.min(minLongitude, location.longitude)
}
let centerLatitude = CLLocationDegrees((maxLatitude + minLatitude) * 0.5)
let centerLongitude = CLLocationDegrees((maxLongitude + minLongitude) * 0.5)
return .init(latitude: centerLatitude, longitude: centerLongitude)
}
}
Upvotes: 1
Reputation: 502
And Swift 5 compatible extension
extension Array where Element == CLLocationCoordinate2D {
func center() -> CLLocationCoordinate2D {
var maxLatitude: Double = -200;
var maxLongitude: Double = -200;
var minLatitude: Double = Double(MAXFLOAT);
var minLongitude: Double = Double(MAXFLOAT);
for location in self {
if location.latitude < minLatitude {
minLatitude = location.latitude;
}
if location.longitude < minLongitude {
minLongitude = location.longitude;
}
if location.latitude > maxLatitude {
maxLatitude = location.latitude;
}
if location.longitude > maxLongitude {
maxLongitude = location.longitude;
}
}
return CLLocationCoordinate2DMake(CLLocationDegrees((maxLatitude + minLatitude) * 0.5), CLLocationDegrees((maxLongitude + minLongitude) * 0.5));
}
}
Upvotes: 7
Reputation: 16715
You can also get both the center
of an array of CLLocationCoordinate2D
s and a span
.
extension MKCoordinateRegion {
init(coordinates: [CLLocationCoordinate2D]) {
var minLatitude: CLLocationDegrees = 90.0
var maxLatitude: CLLocationDegrees = -90.0
var minLongitude: CLLocationDegrees = 180.0
var maxLongitude: CLLocationDegrees = -180.0
for coordinate in coordinates {
let lat = Double(coordinate.latitude)
let long = Double(coordinate.longitude)
if lat < minLatitude {
minLatitude = lat
}
if long < minLongitude {
minLongitude = long
}
if lat > maxLatitude {
maxLatitude = lat
}
if long > maxLongitude {
maxLongitude = long
}
}
let span = MKCoordinateSpanMake(maxLatitude - minLatitude, maxLongitude - minLongitude)
let center = CLLocationCoordinate2DMake((maxLatitude - span.latitudeDelta / 2), (maxLongitude - span.longitudeDelta / 2))
self.init(center: center, span: span)
}
}
Usage:
let region = MKCoordinateRegion(coordinates: coordinates)
region.center
region.span
Upvotes: 6
Reputation: 77631
Hmm... it depends how you define the centre of the points. Does it depend on the distribution etc...
An easy way to do it is as follows...
//find rect that encloses all coords
float maxLat = -200;
float maxLong = -200;
float minLat = MAXFLOAT;
float minLong = MAXFLOAT;
for (int i=0 ; i<[locations count] ; i++) {
CLLocationCoordinate2D location = [locations objectAtIndex:i];
if (location.latitude < minLat) {
minLat = location.latitude;
}
if (location.longitude < minLong) {
minLong = location.longitude;
}
if (location.latitude > maxLat) {
maxLat = location.latitude;
}
if (location.longitude > maxLong) {
maxLong = location.longitude;
}
}
//Center point
CLLocationCoordinate2D center = CLLocationCoordinate2DMake((maxLat + minLat) * 0.5, (maxLong + minLong) * 0.5);
This will give the center of the rect covering all the points. However it does not take the spread into account.
i.e.
. = point
X = centre
..... X .
EDIT
Corrected some of the maths.
Upvotes: 14
Reputation: 311
Fogmeisters answer will work but has 3 errors, which I have corrected below:
//find rect that encloses all coords
float maxLat = -200;
float maxLong = -200;
float minLat = MAXFLOAT;
float minLong = MAXFLOAT;
for (int i=0 ; i<[locations count] ; i++) {
CLLocationCoordinate2D location = [locations objectAtIndex:i];
if (location.latitude < minLat) {
minLat = location.latitude;
}
if (location.longitude < minLong) {
minLong = location.longitude;
}
if (location.latitude > maxLat) {
maxLat = location.latitude;
}
if (location.longitude > maxLong) { //Change to be greater than
maxLong = location.longitude;
}
}
//Center point
//The min's and max's should be ADDED not subtracted
CLLocationCoordinate2D center = CLLocationCoordinate2DMake((maxLat + minLat) * 0.5, (maxLong + minLong) * 0.5);
Upvotes: 1
Reputation: 508
I know it's really late but someone could read this and help himself Using Fogmeister answer you could create a MKCoordinateRegion
CLLocationDegrees minLat,minLng,maxLat,maxLng;
for(CLLocationCoordinate2D coordinate in coordinates) {
minLat = MIN(minLat, coordinate.latitude);
minLng = MIN(minLng, coordinate.longitude);
maxLat = MAX(maxLat, coordinate.latitude);
maxLng = MAX(maxLng, coordinate.longitude);
}
CLLocationCoordinate2D coordinateOrigin = CLLocationCoordinate2DMake(minLat, minLng);
CLLocationCoordinate2D coordinateMax = CLLocationCoordinate2DMake(maxLat, maxLng);
MKMapPoint upperLeft = MKMapPointForCoordinate(coordinateOrigin);
MKMapPoint lowerRight = MKMapPointForCoordinate(coordinateMax);
//Create the map rect
MKMapRect mapRect = MKMapRectMake(upperLeft.x,
upperLeft.y,
lowerRight.x - upperLeft.x,
lowerRight.y - upperLeft.y);
//Create the region
MKCoordinateRegion region = MKCoordinateRegionForMapRect(mapRect);
//THIS HAS THE CENTER, it should include spread
CLLocationCoordinate2D centerCoordinate = region.center;
Greetings!!!
Upvotes: 5
Reputation: 8294
If you're looking for the average as the center then you sum up all the lats and longs into their own totals and then divide by the number of coordinates you have, pretty standard maths.
(Note this won't work if you coords span the date line)
Upvotes: 1