4

Мне нужно выяснить, как настроить MKMapSnapshotterOptions, чтобы сделать снимок аэрофотоснимков/спутниковых изображений, связанных с полигональной областью земли.Как определить правильную высоту для MKMapCamera, фокусируясь на MKPolygon

Заполнение свойств 'region', 'scale', 'size' и 'mapType' тривиально, так как у меня есть MKPolygon для работы. Трудная часть заключается в настройке «камеры» - в моем конкретном случае я использую MKMapSnapshotter независимо от MKMapView (фактически, даже не в основном потоке).

Однако я бы предпочел сориентировать моментальный снимок так, чтобы он соответствовал границам многоугольника на основе ненулевого заголовка, то есть область, в которой я делаю снимок, имеет «начало» и «конец», который я хотел бы сориентировать снизу вверх в результирующем изображении. Поскольку многоугольник в принципе никогда не будет естественным образом ориентирован на курс 0 градусов, мне нужно будет определить «centerCoordinate», «заголовок» и «высота».

Поскольку у меня есть координаты многоугольника, я могу легко получить центральную координату и желаемый заголовок. Первая координата полигона коррелирует с «началом» формы и конца (или другой координаты в мой случай) коррелирует с «концом».

Определение высоты означает, что это сложнее; Я хочу убедиться, что область многоугольника заканчивается заполнением пропорции снимка моментального снимка, который я хочу отобразить. Как вычислить правильную высоту для использования с MKMapCamera, не полагаясь на селектор «setRegion» MKMapView?

ответ

17

Для того, чтобы решить эту проблему, я в конечном итоге делает следующее:

1) вращение MKPolygon вокруг него это центр координат, чтобы устранить проблемы заголовка/вращения при определении ограничивающего прямоугольника: с просьбой об MKPolygon для него это «boundingMapRect 'без этого будет возвращать любой минимальный прямоугольник, подходящий по всей фигуре. Если длинный, тощий многоугольник оказался ориентированным по диагонали с северо-востока на юго-запад, ограничивающий прямоугольник был бы почти квадратным. Выполнение вращения позволяет учитывать заголовок многоугольника при определении его соотношения сторон.

2) установка прямоугольного прямоугольника с корректировкой заголовка многоугольника в пропорции окна просмотра моментальных снимков: это гарантирует, что очень высокий «многоугольник» по-прежнему будет правильно размещаться в широкоэкранном видовом экране и наоборот.

3) [Удален из моего примера кода] Создания полигона результирующего кадра скорректированных ограничивающего прямоугольника и вращая его обратно к первоначальному заголовку, используя центр многоугольника координат: Это, вероятно, будет необходимо при работе с большими регионами , так как следующий шаг включает измерение горизонтальных/вертикальных ограничивающих расстояний. В моем случае я работаю с очень маленькими регионами, которые не должны сильно влиять на кривизну Земли, чтобы иметь реальное значение.

4) определения общей области горизонтального и вертикальные ограничивающей в метрах

5), используя больший размер (размер) два расстояний для формирования базы измерения треугольника, где А = минимальной координаты расположения на оси , B = максимальное местоположение координаты на оси и C = местоположение камеры (центральная координата многоугольника)

На данный момент я был немного озадачен тем, как решить высоту полученного треугольника, не имея, по крайней мере, 1 из углов.При выполнении некоторых тестов с использованием экземпляра MKMapView оказывается, что апертура MKMapCamera составляет около 30 градусов - это независимо от увеличения соотношения сторон экрана просмотра, соотношения сторон многоугольника или любого другого фактора, кроме кривизны земли. Возможно, я ошибаюсь в этом утверждении.

5) Используя угол апертуры, наблюдаемую в моих тестах, рассчитать необходимую высоту с помощью (размер/2)/тангенс (aperture_angle_in_radians/2)

Видя, сколько времени я в конечном итоге расходы на это, я ве решил опубликовать комбо вопрос/ответ на StackOverflow в надежде, что это либо: 1) помогает кому-то еще в том же положении 2) исправлен кем-то способ умнее, чем я, и приводит к еще лучшему решению

Благодаря!

ОН, и, конечно же, код:

+ (double)determineAltitudeForPolygon:(MKPolygon *)polygon withHeading:(double)heading andWithViewport:(CGSize)viewport { 
    // Get a bounding rectangle that encompasses the polygon and represents its 
    // true aspect ratio based on the understanding of its heading. 
    MKMapRect boundingRect = [[self rotatePolygon:polygon withCenter:MKMapPointForCoordinate(polygon.coordinate) byHeading:heading] boundingMapRect]; 

    MKCoordinateRegion boundingRectRegion = MKCoordinateRegionForMapRect(boundingRect); 

    // Calculate a new bounding rectangle that is corrected for the aspect ratio 
    // of the viewport/camera -- this will be needed to ensure the resulting 
    // altitude actually fits the polygon in view for the observer. 
    CLLocationCoordinate2D upperLeftCoord = CLLocationCoordinate2DMake(boundingRectRegion.center.latitude + boundingRectRegion.span.latitudeDelta/2, boundingRectRegion.center.longitude - boundingRectRegion.span.longitudeDelta/2); 
    CLLocationCoordinate2D upperRightCoord = CLLocationCoordinate2DMake(boundingRectRegion.center.latitude + boundingRectRegion.span.latitudeDelta/2, boundingRectRegion.center.longitude + boundingRectRegion.span.longitudeDelta/2); 
    CLLocationCoordinate2D lowerLeftCoord = CLLocationCoordinate2DMake(boundingRectRegion.center.latitude - boundingRectRegion.span.latitudeDelta/2, boundingRectRegion.center.longitude - boundingRectRegion.span.longitudeDelta/2); 

    CLLocationDistance hDist = MKMetersBetweenMapPoints(MKMapPointForCoordinate(upperLeftCoord), MKMapPointForCoordinate(upperRightCoord)); 
    CLLocationDistance vDist = MKMetersBetweenMapPoints(MKMapPointForCoordinate(upperLeftCoord), MKMapPointForCoordinate(lowerLeftCoord)); 

    double adjacent; 
    double newHDist, newVDist; 

    if (boundingRect.size.height > boundingRect.size.width) { 
     newVDist = vDist; 
     newHDist = (viewport.width/viewport.height) * vDist; 

     adjacent = vDist/2; 
    } else { 
     newVDist = (viewport.height/viewport.width) * hDist; 
     newHDist = hDist; 

     adjacent = hDist/2; 
    } 

    double result = adjacent/tan(Deg_to_Rad(15)); 
    return result; 
} 

+ (MKPolygon *)rotatePolygon:(MKPolygon *)polygon withCenter:(MKMapPoint)centerPoint byHeading:(double)heading { 
    MKMapPoint points[polygon.pointCount]; 
    double rotation_angle = -Deg_to_Rad(heading); 

    for(int i = 0; i < polygon.pointCount; i++) { 
     MKMapPoint point = polygon.points[i]; 

     // Translate each point by the coordinate to rotate around, use matrix 
     // algebra to perform the rotation, then translate back into the 
     // original coordinate space. 
     double newX = ((point.x - centerPoint.x) * cos(rotation_angle)) + ((centerPoint.y - point.y) * sin(rotation_angle)) + centerPoint.x; 
     double newY = ((point.x - centerPoint.x) * sin(rotation_angle)) - ((centerPoint.y - point.y) * cos(rotation_angle)) + centerPoint.y; 

     point.x = newX; 
     point.y = newY; 

     points[i] = point; 
    } 

    return [MKPolygon polygonWithPoints:points count:polygon.pointCount]; 
} 
+0

Спасибо за просмотр angle_ _30 °. Это то, что я искал. – Tricertops

+0

Это замечательно. 30-градусный угол был отсутствующим параметром – qiksand

 Смежные вопросы

  • Нет связанных вопросов^_^