위도/경도 좌표 주변의 최소 경계 사각형을 결정하는 알고리즘이 있습니까?위도/경도 좌표를 수집 할 최소 경계 사각형을 결정하는 알고리즘
좌표가 너무 멀리 떨어져 있지 않으므로 평평한 지구를 사용하는 것이 좋습니다. 가짜 코드는 괜찮습니다.하지만 누군가 Objective-C에서이 작업을 수행했다면 더 좋을 것입니다. 내가하려는 것은지도에 표시 될 점의 수를 기준으로지도의 확대/축소 수준을 설정하는 것입니다.
위도/경도 좌표 주변의 최소 경계 사각형을 결정하는 알고리즘이 있습니까?위도/경도 좌표를 수집 할 최소 경계 사각형을 결정하는 알고리즘
좌표가 너무 멀리 떨어져 있지 않으므로 평평한 지구를 사용하는 것이 좋습니다. 가짜 코드는 괜찮습니다.하지만 누군가 Objective-C에서이 작업을 수행했다면 더 좋을 것입니다. 내가하려는 것은지도에 표시 될 점의 수를 기준으로지도의 확대/축소 수준을 설정하는 것입니다.
그러면 위 왼쪽 지점 에 대한 위도/경도가 가장 작고 오른쪽 하단 지점에 가장 큰 위도/경도가 표시됩니다. 당신이 원하는 무엇을, 당신은 아마 북위 롱의 최소 및 최대 값을 찾아 당신의 사각형의 경계로 사람들을 사용할 수있는 경우
double minLat = 900;
double minLon = 900;
double maxLat = -900;
double maxLon = -900;
foreach(Point point in latloncollection)
{
minLat = Math.min(minLat, point.lat);
minLon = Math.min(minLon, point.lon);
maxLat = Math.max(maxLat, point.lat);
maxLon = Math.max(maxLon, point.lon);
}
위도와 경도 절대 값이 900을 초과하지 않는다는 것을 알고 있다고해도, 목록의 첫 번째 점에 대한 최소값과 최대 값을 시작한 후 더 나은 값을 찾으려는 것이 더 좋을 것이라고 생각합니다. 리스트의 2 번째의 아이템 – mbritto
. 보다 정교한 솔루션은 다음을 참조하십시오 당신이 목표 - C의 경우
는 당신이이 경우에 당신은 많은 작업을 수행 할 STL을 사용할 수 있습니다, 대신 ++ 목표 - C를 사용할 수 있습니다 당신을 위해 무거운 :
#include <vector>
#include <algorithm>
std::vector<float> latitude_set;
std::vector<float> longitude_set;
latitude_set.push_back(latitude_a);
latitude_set.push_back(latitude_b);
latitude_set.push_back(latitude_c);
latitude_set.push_back(latitude_d);
latitude_set.push_back(latitude_e);
longitude_set.push_back(longitude_a);
longitude_set.push_back(longitude_b);
longitude_set.push_back(longitude_c);
longitude_set.push_back(longitude_d);
longitude_set.push_back(longitude_e);
float min_latitude = *std::min_element(latitude_set.begin(), latitude_set.end());
float max_latitude = *std::max_element(latitude_set.begin(), latitude_set.end());
float min_longitude = *std::min_element(longitude_set.begin(), longitude_set.end());
float max_longitude = *std::max_element(longitude_set.begin(), longitude_set.end());
일반 C++에도 라이브러리가 있습니다. 또한이 코딩을 정적으로 어떻게 코딩하는 것이 좋은 생각일까요? – Foredecker
이것은 표준 호환 C++입니다. 위도 및 경도 벡터의 정적 채우기는 예제에 대한 것입니다 ... 원하는대로 벡터에 항목을 추가 할 수 있습니다. – fbrereto
더 간단한 ObjC 코드가 더 가벼울 때 무거운 들어 올림 각도를 볼 수 있을지 확신하지 못합니다. 어떤 방법 으로든 잘라내는 것은 모든 포인트 값을보고있는 것입니다. –
당신이 가장 오른쪽, 맨 위 가장 왼쪽, 그리고 가장 아래 값을 가져하기 만하면됩니다. 정렬을 통해이 작업을 매우 쉽게 수행 할 수 있습니다. 세트가 너무 크지 않으면 매우 비싸지 않을 것입니다.
compareLatitude:
및 compareLongitude:
이라고하는 위도/경도 메서드를 제공하면 훨씬 쉽습니다.
CGFloat north, west, east, south;
[latLongCollection sortUsingSelector:@selector(compareLongitude:)];
west = [[latLongCollection objectAtIndex:0] longitude];
east = [[latLongCollection lastObject] longitude];
[latLongCollection sortUsingSelector:@selector(compareLatitude:)];
south = [[latLongCollection objectAtIndex:0] latitude];
north = [[latLongCollection lastObject] latitude];
좌표 컬렉션이 NSMutableArray라고 가정하면 정상적으로 작동합니다.
내 배열은 MKAnnotation 객체의 NSMutableArray입니다. 나는 비교를하기 위해 선택기 메소드를 구현하는 가장 좋은 방법을 생각해야 할 것이다. 목록을 수동으로 반복하는 것만 큼 다르지 않습니다. 그러나 이것은 좀 더 "우아한"것입니다. –
이것은 내 앱 중 하나에서 사용하는 방법입니다. 영업지도에 설정하는 경계 사각형을 사용하고 싶어하기 때문에
- (void)centerMapAroundAnnotations
{
// if we have no annotations we can skip all of this
if ([[myMapView annotations] count] == 0)
return;
// then run through each annotation in the list to find the
// minimum and maximum latitude and longitude values
CLLocationCoordinate2D min;
CLLocationCoordinate2D max;
BOOL minMaxInitialized = NO;
NSUInteger numberOfValidAnnotations = 0;
for (id<MKAnnotation> a in [myMapView annotations])
{
// only use annotations that are of our own custom type
// in the event that the user is browsing from a location far away
// you can omit this if you want the user's location to be included in the region
if ([a isKindOfClass: [ECAnnotation class]])
{
// if we haven't grabbed the first good value, do so now
if (!minMaxInitialized)
{
min = a.coordinate;
max = a.coordinate;
minMaxInitialized = YES;
}
else // otherwise compare with the current value
{
min.latitude = MIN(min.latitude, a.coordinate.latitude);
min.longitude = MIN(min.longitude, a.coordinate.longitude);
max.latitude = MAX(max.latitude, a.coordinate.latitude);
max.longitude = MAX(max.longitude, a.coordinate.longitude);
}
++numberOfValidAnnotations;
}
}
// If we don't have any valid annotations we can leave now,
// this will happen in the event that there is only the user location
if (numberOfValidAnnotations == 0)
return;
// Now that we have a min and max lat/lon create locations for the
// three points in a right triangle
CLLocation* locSouthWest = [[CLLocation alloc]
initWithLatitude: min.latitude
longitude: min.longitude];
CLLocation* locSouthEast = [[CLLocation alloc]
initWithLatitude: min.latitude
longitude: max.longitude];
CLLocation* locNorthEast = [[CLLocation alloc]
initWithLatitude: max.latitude
longitude: max.longitude];
// Create a region centered at the midpoint of our hypotenuse
CLLocationCoordinate2D regionCenter;
regionCenter.latitude = (min.latitude + max.latitude)/2.0;
regionCenter.longitude = (min.longitude + max.longitude)/2.0;
// Use the locations that we just created to calculate the distance
// between each of the points in meters.
CLLocationDistance latMeters = [locSouthEast getDistanceFrom: locNorthEast];
CLLocationDistance lonMeters = [locSouthEast getDistanceFrom: locSouthWest];
MKCoordinateRegion region;
region = MKCoordinateRegionMakeWithDistance(regionCenter, latMeters, lonMeters);
MKCoordinateRegion fitRegion = [myMapView regionThatFits: region];
[myMapView setRegion: fitRegion animated: YES];
// Clean up
[locSouthWest release];
[locSouthEast release];
[locNorthEast release];
}
좋은 코드 조각, 공유 주셔서 감사합니다. – Goles
Butch Anton의 getDistanceFrom : 메시지가 iPhone OS 3.2부터 제공되지 않습니다. 코드 은 이제 distanceFromLocation :을 대신 사용해야합니다. – jessecurry
public BoundingRectangle calculateBoundingRectangle()
{
Coordinate bndRectTopLeft = new Coordinate();
Coordinate bndRectBtRight = new Coordinate();
// Initialize bounding rectangle with first point
Coordinate firstPoint = getVertices().get(0);
bndRectTopLeft.setLongitude(firstPoint.getLongitude());
bndRectTopLeft.setLatitude(firstPoint.getLatitude());
bndRectBtRight.setLongitude(firstPoint.getLongitude());
bndRectBtRight.setLatitude(firstPoint.getLatitude());
double tempLong;
double tempLat;
// Iterate through all the points
for (int i = 0; i < getVertices().size(); i++)
{
Coordinate curNode = getVertices().get(i);
tempLong = curNode.getLongitude();
tempLat = curNode.getLatitude();
if (bndRectTopLeft.getLongitude() > tempLong) bndRectTopLeft.setLongitude(tempLong);
if (bndRectTopLeft.getLatitude() < tempLat) bndRectTopLeft.setLatitude(tempLat);
if (bndRectBtRight.getLongitude() < tempLong) bndRectBtRight.setLongitude(tempLong);
if (bndRectBtRight.getLatitude() > tempLat) bndRectBtRight.setLatitude(tempLat);
}
bndRectTopLeft.setLatitude(bndRectTopLeft.getLatitude());
bndRectBtRight.setLatitude(bndRectBtRight.getLatitude());
// Throw an error if boundaries contains poles
if ((Math.toRadians(topLeft.getLatitude()) >= (Math.PI/2)) || (Math.toRadians(bottomRight.getLatitude()) <= -(Math.PI/2)))
{
// Error
throw new Exception("boundaries contains poles");
}
// Now calculate bounding x coordinates
// Calculate it along latitude circle for the latitude closure to the
// pole
// (either north or south). For the other end the loitering distance
// will be slightly higher
double tempLat1 = bndRectTopLeft.getLatitude();
if (bndRectBtRight.getLatitude() < 0)
{
if (tempLat1 < (-bndRectBtRight.getLatitude()))
{
tempLat1 = (-bndRectBtRight.getLatitude());
}
}
bndRectTopLeft.setLongitude(bndRectTopLeft.getLongitude());
bndRectBtRight.setLongitude(bndRectBtRight.getLongitude());
// What if international date line is coming in between ?
// It will not affect any calculation but the range for x coordinate for the bounding rectangle will be -2.PI to +2.PI
// But the bounding rectangle should not cross itself
if ((Math.toRadians(bottomRight.getLongitude()) - Math.toRadians(topLeft.getLongitude())) >= (2 * Math.PI))
{
// Throw some error
throw new Exception("Bounding Rectangle crossing itself");
}
return new BoundingRectangle(bndRectTopLeft, bndRectBtRight);
}
이 ...
을 지역 횡단 기둥 경우 예외를 처리하는 알고리즘이 있다는 사실을 고려해야 할 필요가 위도와 경도는 구 좌표계이며지도는 2 차원 좌표계를 사용합니다. 지금까지 게시 된 솔루션 중 아무 것도이 점을 고려하지 않아 잘못된 경계 사각형으로 끝나지 만 다행히도 WWDC 2013의이 샘플 코드에있는 "MapKit의 새로운 기능"인 MKMapPointForCoordinate 메서드를 사용하여 유효한 솔루션을 만드는 것은 매우 쉽습니다. 세션 비디오.
MKMapRect MapRectBoundingMapPoints(MKMapPoint points[], NSInteger pointCount){
double minX = INFINITY, maxX = -INFINITY, minY = INFINITY, maxY = -INFINITY;
NSInteger i;
for(i = -; i< pointCount; i++){
MKMapPoint p = points[i];
minX = MIN(p.x,minX);
minY = MIN(p.y,minY);
maxX = MAX(p.x,maxX);
maxY = MAX(p.y,maxY);
}
return MKMapRectMake(minX,minY,maxX - minX,maxY-minY);
}
CLLocationCoordinate2D london = CLLocationCoordinate2DMake(51.500756,-0.124661);
CLLocationCoordinate2D paris = CLLocationCoordinate2DMake(48.855228,2.34523);
MKMapPoint points[] = {MKMapPointForCoordinate(london),MKMapPointForCoordinate(paris)};
MKMapRect rect = MapRectBoundingMapPoints(points,2);
rect = MKMapRectInset(rect,
-rect.size.width * 0.05,
-rect.size.height * 0.05);
MKCoordinateRegion coordinateRegion = MKCoordinateRegionForMapRect(rect);
원하는 경우 특수 효과의 NSArray에서 작동하도록 메소드를 쉽게 변경할 수 있습니다. 예 : 경도 -178 가지고, -175, +
: 쓴 @malhal
- (MKCoordinateRegion)regionForAnnotations:(NSArray*)anns{
MKCoordinateRegion r;
if ([anns count] == 0){
return r;
}
double minX = INFINITY, maxX = -INFINITY, minY = INFINITY, maxY = -INFINITY;
for(id<MKAnnotation> a in anns){
MKMapPoint p = MKMapPointForCoordinate(a.coordinate);
minX = MIN(p.x,minX);
minY = MIN(p.y,minY);
maxX = MAX(p.x,maxX);
maxY = MAX(p.y,maxY);
}
MKMapRect rect = MKMapRectMake(minX,minY,maxX - minX,maxY-minY);
rect = MKMapRectInset(rect,
-rect.size.width * 0.05,
-rect.size.height * 0.05);
return MKCoordinateRegionForMapRect(rect);
}
가 정확한지, 모든 해답은 여기에 여기에 잘못과 예입니다 : 여기 내 응용 프로그램에서 사용하고있는 방법은 175, +178. 다른 답변에 따르면, 그 둘레의 가장 작은 경계 상자는 -178 (서쪽) : +178 (동쪽)이며 전체 세계입니다.이것은 사실이 아닙니다. 지구가 둥글다면 뒤에서 보면 +175 (서쪽) : -175 (동쪽)의 더 작은 경계 상자를 갖게됩니다.
이 문제는 경도가 -180/+ 180에 가까울 때 발생합니다. 내 두뇌는 위도에 대해 생각하려고 애쓰지만, 문제가있는 경우 Google지도가 "돌아 다니지"않는 극지방에 있으므로 문제가되지 않습니다 (폴 이후). 여기
는 예를 들어 용액 (커피 스크립트)입니다 :이 더 이상 당신의 최대 관심사 (2 년 후)입니다 확신# This is the object that keeps the mins/maxes
corners =
latitude:
south: undefined
north: undefined
longitude:
normal:
west: undefined
east: undefined
# This keeps the min/max longitude after adding +360 to negative ones
reverse:
west: undefined
east: undefined
points.forEach (point) ->
latitude = point.latitude
longitude = point.longitude
# Setting latitude corners
corners.latitude.south = latitude if not corners.latitude.south? or latitude < corners.latitude.south
corners.latitude.north = latitude if not corners.latitude.north? or latitude > corners.latitude.north
# Setting normal longitude corners
corners.longitude.normal.west = longitude if not corners.longitude.normal.west? or longitude < corners.longitude.normal.west
corners.longitude.normal.east = longitude if not corners.longitude.normal.east? or longitude > corners.longitude.normal.east
# Setting reverse longitude corners (when looking from the other side)
longitude = if longitude < 0 then longitude + 360 else longitude
corners.longitude.reverse.west = longitude if not corners.longitude.reverse.west? or longitude < corners.longitude.reverse.west
corners.longitude.reverse.east = longitude if not corners.longitude.reverse.east? or longitude > corners.longitude.reverse.east
# Choosing the closest corners
# Extreme examples:
# Same: -174 - -178 = +186 - +182 (both eastgtive)
# Better normal: +2 - -4 < 176 - +2 (around the front)
# Better reverse: +182 - +178 < +178 - -178 (around the back)
if corners.longitude.normal.east - corners.longitude.normal.west < corners.longitude.reverse.east - corners.longitude.reverse.west
corners.longitude = corners.longitude.normal
else
corners.longitude = corners.longitude.reverse
corners.longitude.west = corners.longitude.west - 360 if corners.longitude.west > 180
corners.longitude.east = corners.longitude.east - 360 if corners.longitude.east > 180
# Now:
# SW corner at: corners.latitude.south/corners.longitude.west
# NE corner at: corners.latitude.north/corners.longitude.east
,하지만 당신은 그것을 가능 알아야한다 - 이론적으로 적어도 - 나열된 모든 답변이 훌륭하게 실패합니다. 태평양의 한 개 이상의 다각형을 고려해보십시오 (왼쪽 아래의 X는 +170, 오른쪽 상단의 X는 -170). 바운딩 박스를 적합하게 만들려고 머리를 녹일 것입니다. 이 기사 : http://www.stonybrook.edu/libmap/coordinates/seriesa/no2/a2.htm (Global Gotchas 섹션)은 문제를 해결할 수 없으며 해결할 필요가 없다는 것을 의미합니다. – tomfumb