Мне нужно нарисовать геопроецированный круг на карте.например, я хочу, чтобы центр был определен с точки зрения широты и долготы, а его радиус - в метрах.Я использую KDE Marble
.В API есть функция drawEllipse
, которая принимает центр в виде (широта, долгота), ширину и высоту эллипса.
GeoPainter::drawEllipse(const GeoDataCoordinates& center, qreal width, qreal height, bool isGeoProjected = false)
Для эллипса с гео-проекцией ширинаи высота считается в градусах.Однако мне нужно, чтобы они были в метрах.Простого преобразования между градусами и метрами не существует, поскольку оно зависит от положения центра на глобусе.
Мне нужно преобразовать радиус круга (в метрах) в пару степеней смещения векторауказывая на центр от центра земли.
Я также использую геометрию наддува для других геометрических расчетов.Есть ли в boost-geometry
какая-либо функция, которая выполняет это преобразование?
ОБНОВЛЕНИЕ I
Сначала я попытался получить две координаты GeoDataCoordinates, одна из которых находится в центре, а другая - по периметру.Я ожидал, что разница между их широтой и долготой будет работать с функцией drawEllipse
.
painter->drawEllipse(_center, std::abs(_border.longitude(GeoDataCoordinates::Degree)-_center.longitude(GeoDataCoordinates::Degree)), std::abs(_border.latitude(GeoDataCoordinates::Degree)-_center.latitude(GeoDataCoordinates::Degree)), true);
Однако она дает эллипс намного меньше, чем я ожидал.Граница, которая должна была быть на окружности, находится за пределами эллипса.
ОБНОВЛЕНИЕ II
Затем я попытался использовать формулу центрального угла в wikipedia
double angular_distance = acos(
(sin(_center.latitude(GeoDataCoordinates::Radian))*sin(_border.latitude(GeoDataCoordinates::Radian)))
+(cos(_center.latitude(GeoDataCoordinates::Radian))*cos(_border.latitude(GeoDataCoordinates::Radian)))
*(double)cos(std::abs(_border.longitude(GeoDataCoordinates::Radian)-_center.longitude(GeoDataCoordinates::Radian)))
);
painter->drawEllipse(_center, stmr::internal::rad2deg(angular_distance), stmr::internal::rad2deg(angular_distance), true);
Результаты мало чем отличаются от предыдущего.Однако на этот раз эллипс немного больше предыдущего.
ОБНОВЛЕНИЕ III
Отношение расстояний между дугой и окружностью большой окружности сферы используется для вычисления углового смещения в ответе @ ttemple
painter->drawEllipse(_center, 2*(distance/earthRadiusKm)* 180.0/3.14159, 2*(distance/earthRadiusKm)* 180.0/3.14159, true);
создает правильный эллипс.
Поэтому я умножил углы на 2.0
на ОБНОВЛЕНИЕ II код, который также дал похожий (например, ОБНОВЛЕНИЕ III ) результат.
ОБНОВЛЕНИЕ IV
Но проблема с drawEllipse
заключается в том, что он на самом деле рисуетмногоугольник с гораздо меньшим количеством точек в уменьшенном состоянии.Иногда это выглядит как квадрат.
Поэтому лучше рисовать больше точек на окружности эллипса, чтобы ограждение выглядело как круг в увеличенном виде. KDE Forum Link , размещенный в комментариях, делает то же самое.
GeoDataLineString ellipse;
qreal lon = 0.0;
qreal lat = 0.0;
int precision = 180;
for ( int i = 0; i < precision; ++i){
qreal t = 1.0 - 2.0 * (qreal)(i) / (qreal)(precision);
lat = center.latitude(GeoDataCoordinates::Degree) + 0.5 * radius * sqrt(1.0 - t * t);
lon = center.longitude(GeoDataCoordinates::Degree) + 0.5 * radius * t;
ellipse << GeoDataCoordinates(lon, lat, 0.0, GeoDataCoordinates::Degree);
}
for ( int i = 0; i < precision; ++i){
qreal t = 2.0 * (qreal)(i) / (qreal)(precision) - 1.0;
lat = center.latitude(GeoDataCoordinates::Degree) - 0.5 * radius * sqrt(1.0 - t * t);
lon = center.longitude(GeoDataCoordinates::Degree) + 0.5 * radius * t;
ellipse << GeoDataCoordinates(lon, lat, 0.0, GeoDataCoordinates::Degree);
}
painter->drawPolyline(ellipse);
Однако он рисует круг с гораздо большим радиусом, чем ввод.Я думаю, что фрагмент, размещенный там, является неполным.Есть неиспользованные условные блоки, которые я игнорировал в своем коде.Также в коде конкретно упоминается в комментариях, что радиус забора нужно указывать в км.Я так и сделал.Также я не понял, что за математика стоит за этим.Он не использует Радиус Земли нигде во фрагменте.Может быть небольшая поправка к этому коду даст лучший эллипс.Математика выглядит как некоторая параметрическая кривая, которая производит половину эллипса.Но здесь нет ссылки на уравнение.
Также это работает только в первом квадранте, где значения lat и lon положительны