На главную... Продукты | Технологии | Классификаторы | Проекты | Скачать | Цены| Форум | Статьи | Обучение | Контакты

Поворот векторного объекта

Поиск  Пользователи  Правила  Войти
Форум » Настольные приложения » GIS ToolKit, GIS ToolKit Active, ГИС Конструктор для Windows
Страницы: 1 2 След.
RSS
Поворот векторного объекта
 
Добрый день!

Пишу на delphi7 c использованием Gistools 11.6.2.

Вопрос в следующем: как повернуть векторный объект на заданный угол?
процедура mapObj.RotateObject понятна, но мне нужно рассчитать угол поворота
от текущего состояния угла объекта, как его получить или рассчитать?
 
Поврот векторного объекта возможен при отсуствии флага "горизонтально", это первый момент.
Второй момент: чтобы расчитать текущий угол, на который повёрнут Ваш векторный объект, Вам нужно считать две его координаты, и посчитать декартов угол.
Изменение угла векторного объекта, осуществоляется методом изменения кординаты одной точки метрики относительно другой.
Угол можно вычисить :
Код
uses Math;

var P1, P2 : TDoublePoint;
    angle  : double;
begin
  mapGetPlanePoint(Obj, @p1, 1);
  mapGetPlanePoint(Obj, @p2, 1);
  angle := arctan2(p2.y-p1.y, p2.x-p1.x);  
end;


angle содержит текущий угол. Если от Вашего угла (ALPHA) отнять значение angle. у Вас получится та разница, на которую нужно довернуть векторный объект.
Не тот глуп кто не знает, а тот, кто не знает где искать.
 
Цитата
KFF пишет:
Поврот векторного объекта возможен при отсуствии флага "горизонтально", это первый момент.
Второй момент: чтобы расчитать текущий угол, на который повёрнут Ваш векторный объект, Вам нужно считать две его координаты, и посчитать декартов угол.

Федор спасибо за ответ!

Насколько я понял, расчет углов поворота объектов в GisToolKit отсутствует,
разработчики посчитали этот функционал неважным, интересно почему?
Изменено: Victor Fedyashev - 20.11.2012 10:22:26
 
А этот функционал не по теме?

Код
 // Вычисление азимута участка объекта (стороны)
 // Возвращает величину угла в радианах
 // Если геодезия не поддерживается, то вычисляется дирекционный угол
 // Для последней точки вычисляет направление на первую точку
 // У замкнутых объектов первая и последняя точки совпадают
 // info  - идентификатор объекта карты в памяти
 // number - номер точки, начиная с 1
 // subject - номер подобъекта (если = 0, обрабатывается объект)
 // При ошибке возвращает 0 (при совпадении точек также)

_MAPIMP double _MAPAPI mapSideAzimuth(HOBJ info,long int number,      //16/01/01
long int subject);
_MAPIMP long int _MAPAPI mapSideAzimuthEx(HOBJ info,long int number,
long int subject, double * azimuth);

 // Вычисление дирекционного угла участка объекта (стороны)
 // Возвращает величину угла в радианах
 // Для последней точки вычислет направление на первую точку
 // У замкнутых объектов перва и последн точки совпадают
 // info  - идентификатор объекта карты в памяти
 // number - номер точки, начиная с 1
 // subject - номер подобъекта (если = 0, обрабатывается объект)
 // При ошибке возвращает 0 (при совпадении точек также)

_MAPIMP double _MAPAPI mapSideDirection(HOBJ info,long int number,
long int subject/* = 0*/);


Код
 // Определение угла наклона биссектрисы угла, заданного
 // точками p1,p2,p3 с вершиной в точке p2
 // Определение угла наклона биссектрисы угла, заданного
 // точками p1,p2,p3 с вершиной в точке p2
 // Возвращаемый угол задан относительно оси X, его положительное
 // направление соответствует положительному направлению оси Y

_MAPIMP double _MAPAPI mapBisectorAngle(DOUBLEPOINT * p1, DOUBLEPOINT * p2,
DOUBLEPOINT * p3);


Код
 // Прямая геодезическая задача на эллипсоиде                       // 03/04/12
 // Для расстояния не более 250 км координаты определяются с ошибкой до 0,0001",
 // а обратный азимут - до 0,001", что соответствует триангуляции 1 класса
 // Способ вспомогательной точки по методу Красовского
 // Метод предназначен для расстояний меньше радиуса Земли
 // Вычисления выполняются на текущем эллипсоиде, установленном
 // в документе - mapSetDocProjection
 // hmap     - идентификатор открытых данных
 // b1,l1    - геодезические координаты исходной точки
 // angle1   - азимут на вторую точку
 // distance - расстояние до второй точки
 // b2,l2    - рассчитанные координаты второй точки
 // angle2   - рассчитанный азимут со второй точки на первую
 //            (если angle2, то обратный азимут не вычисляется)
 // При ошибке в параметрах возвращает 0

_MAPIMP  long int _MAPAPI mapDirectPositionComputation(HMAP hmap,
double b1, double l1, double angle1,
double distance,
double * b2, double * l2, double * angle2);

 // Обратная геодезическая задача на эллипсоиде                     // 03/04/12
 // Для расстояния не более 180 градусов по широте
 // Выполняется построение ортодромии функцией mapOrthodromeObject
 // и запрос длины объекта и азимута первого отрезка
 // Точность порядка точности триангуляции 1 класса
 // Вычисления выполняются на текущем эллипсоиде, установленном
 // в документе - mapSetDocProjection
 // hmap     - идентификатор открытых данных
 // b1,l1    - геодезические координаты первой точки
 // b2,l2    - геодезические координаты второй точки
 // angle    - рассчитанный азимут с первой точки на вторую
 // Возвращает расстояние между заданными точками на текущем эллипсоиде
 // При ошибке в параметрах возвращает 0

_MAPIMP double _MAPAPI mapInversePositionComputation(HMAP hmap,
double b1, double l1,
double b2, double l2,
double * angle);



Код
 // Повернуть объект вокруг заданной в прямоугольной системе точки   // 15/01/07
 // на заданный угол
 // info   - идентификатор объекта карты в памяти
 // center - координаты точки, вокруг которой поворачивается объект (метры)
 // angle  - угол поворота по часовой стрелке (радианы, от -PI до +PI)
 // При ошибке возвращает 0

_MAPIMP long int _MAPAPI mapRotateObject(HOBJ info, DOUBLEPOINT * center, double * angle);


Код
  /*********************************************************
  **
  *     ФУНКЦИИ НАСТРОЙКИ ОТОБРАЖЕНИЯ ЭЛЕКТРОННОЙ КАРТЫ    *
  *                     С ПОВОРОТОМ                        *
  **
  *********************************************************/

 // Функция настройки отображения карты с поворотом
 //  hmap     - идентификатор открытых данных
 //  angle    - угол поворота карты в плане с вершиной в
 //             юго-западном углу карты (от -Pi до Pi)
 //  fixation - угол сектора фиксации поворота отображения карты
 //             относительно предыдущего положения (от 0 до Pi/6).
 //             По умолчанию = Pi/18 (10 градусов)
 // Угол fixation используется для минимизации дрожания изображения 
 // при движении по повернутой карте по прямой (или почти по прямой), 
 // когда при последовательном вызове функции подаются близкие 
 // значения угла поворота (angle). В случае, если разность между 
 // текущим углом поворота и требуемым будет меньше fixation, 
 // то новый угол поворота не устанавливается.
 // Возвращает значение установленного угла поворота.
 // При ошибке возвращает 0

_MAPIMP double _MAPAPI mapSetupTurn(HMAP hmap, double angle,
double fixation);

 // Активен ли поворот ?
 // hmap - идентификатор открытых данных
 // Возвращает (1 - активен, 0 - нет)

_MAPIMP long int _MAPAPI mapTurnIsActive(HMAP hmap);

 // Запросить угол поворота
 // hmap - идентификатор открытых данных
 // Возвращает значения от -Pi до Pi

_MAPIMP double _MAPAPI mapGetTurnAngle(HMAP hmap);
 
Функционал конечно по теме, но частично и как его использовать в Delphi с библиотекой gisacces.dll?


Передо мной стоит задача движения объекта по заданной ломаной траектории (трассе).

1. На первом шаге нужно выровнять направления трассы и объекта, для этого нужно получить их углы, вычислить разницу и довернуть объект по направлению трассы

Как получить угол направления векторного объекта применительно к Delphi на основании его метрики?

С поворотом векторного объекта разобрался:
ТMapObj.RotateObject(tDPoint,angle),
где tDPoint :TDoublePoint – точка объекта, относительно которой осуществляется поворот
     angle:double – угол поворота заданный в радианах.

2. Далее с интервалом таймера нужно вычислять отрезки пути объекта, исходя из его скорости и перемещать его по направлению трассы.

В данной задаче из перечисленного функционала применима только функция поворота объекта.
 
Цитата
Victor Fedyashev пишет:
Функционал конечно по теме, но частично и как его использовать в Delphi с библиотекой gisacces.dll?

Вхожу в папку с исходными текстами GIS ToolKit.
Запускаю поиск по имени функции mapSideDirection:

Нахожу MAPAPI.INC:

// Вычисление дирекционного угла участка объекта (стороны)
// Возвращает величину угла в радианах
// Для последней точки вычислет направление на первую точку
// У замкнутых объектов перва и последн точки совпадают
// Obj     - идентификатор объекта карты в памяти
// number  - номер точки; начиная с 1
// subject - номер подобъекта (если = 0; обрабатывается объект)
// При ошибке возвращает 0 (при совпадении точек также)

function mapSideDirection(Obj:HObj;number:integer;
                         subject:integer):double;
 {$IFNDEF LINUXAPI} stdcall {$ELSE} cdecl {$ENDIF};
 external sGisAcces;


Эти функции есть и в свойствах компонента объекта.

Только Вам ничего поворачивать не нужно.
Первая точка - это координаты объекта.
Вторая точка - это направление объекта.

Если у Вас есть объект трасса, то Вы вызываете функцию:
Код
  // Найти точку на контурах объекта и подобъектов,
  // ближайшую к заданной
  // hMap    - идентификатор открытой карты,
  // info    - идентификатор объекта в памяти
  // pointin - координаты точки в прямоугольной
  //           системе координат , в метрах на местности
  // Возвращает номер точки метрики за которой расположена
  // точка на контуре или ноль при ошибке
  // Координаты точки (в метрах) помещаются по адресу pointout

_MAPIMP  long int _MAPAPI mapSeekNearVirtualPoint(HMAP hMap, HOBJ info,
DOUBLEPOINT * pointin, DOUBLEPOINT * pointout);
 


чтобы притянуть объект к трассе (если он рядом).
Вторую точку можно взять на трассе рядом с объектом или использовать азимут, который снимается с навигатора вместе с координатами (это лучше, поскольку реально).

Если брать вторую точку с трассы, то можно использовать возвращаемое значение из функции mapSeekNearVirtualPoint - номер точки. Стало быть Вам нужно взять координаты точки на одну меньше (если едете к началу трассы) или на одну больше (если едете к концу трассы).

Дальше сами додумывайте.
 
Олег, спасибо за советы, разобрался с Вашей помощью с углами и поворотами векторных объектов.
Успехов Вам!
 
Апну тему.  Пытаюсь тоже разобраться с поворотом векторного знака. Поворачивает, но не туда куда я ожидаю, хотя все вычисляемые значения выглядят корректными. Пример кода ниже. Работаю на карте  меркатора, в epsg 3857.

Надеюсь, что развернет на angle: 1.43417619179084 в рад. А по факту азимут иной. Или возможно легче можно сделать? Задача нос самолета держать по курсу траектории.

Код
    const double x1 = 7400229.988;
    const double y1 = 4131918.366;
    const double x2 = 7415961.944;
    const double y2 = 4253383.378;
    HMAP hMap = mapOpenDataUn(WTEXT("/home/okbadmin/GIS/tmp/cmake/map/map.sit"), GENERIC_WRITE);
    cout << "Is map opened: " << hMap << endl;
    HOBJ object = mapCreateObject(hMap);
    auto findObject = mapSeekObject(hMap, object, mapListName(object), 4);
    cout << " Is found: " << findObject << " listname " << object << endl;
    double angle = 0;
    double Bx1 = x1;
    double Ly1 = y1;
    double Bx2 = x2;
    double Ly2 = y2;
    mapPlaneToGeo(hMap, &Bx1, &Ly1);
    mapPlaneToGeo(hMap, &Bx2, &Ly2);
    auto errorCode = mapInversePositionComputation(hMap, Bx1, Ly1, Bx2, Ly2, &angle);
    auto currentAzimuth = mapSideAzimuth(findObject, 1, 0);
    double centerX = Bx2;
    double centerY = Ly2;
    double directionX = 0;
    double directionY = 0;
    mapDirectPositionComputation(hMap, centerX, centerY, angle, 100, &directionX, &directionY, 0);
    mapGeoToPlane(hMap, &centerX, &centerY);
    mapGeoToPlane(hMap, &directionX, &directionY);
    cout.precision(std::numeric_limits<double>::digits10);
    cout << " plane " << centerX << " " << centerY << " " << directionX << " " << directionY << endl;
    cout << " angle: " << angle << " azumuth: " << currentAzimuth << std::endl;
    mapUpdatePointPlane(findObject, centerX, centerY, 1);
    mapUpdatePointPlane(findObject, directionX, directionY, 2);
    auto isCommited = mapCommitObject(findObject);
    cout << " isCommited " << isCommited << std::endl;
Изменено: Алексей - 23.06.2021 16:11:43
 
Расстояние порядка 250 км.
Геодезическая задача решается через ортодромию.
Это "легкая" дуга для цилиндрических проекций.

mapInversePositionComputation считает азимут в исходной точке для дуги. Он отличается от азимута прямой, но лететь нужно по нему.

Если задача показать направление самолета на вторую точку для красоты, без попытки управлять полетом, то тут достаточно школьных формул для треугольника.

Вторая точка направления - это конечная точка маршрута без всяких вычислений, но можно ее притянуть поближе (по подобию треугольников).
В этом случае найти вторую точку на отрезке на заданном расстоянии можно через mapSeekVirtualPointByDistance()
 
Я наношу точку directionX, directionY на карту и вижу, что она там где должна быть. ТО есть вычисления верны. Правильно ли я обновляю координаты векторного знака?

mapUpdatePointPlane(findObject, centerX, centerY, 1);
mapUpdatePointPlane(findObject, directionX, directionY, 2);

Первая точка центр, вторая - отвечает за направление?
Страницы: 1 2 След.
Читают тему (гостей: 1)



© КБ Панорама, 1991-2024

Регистрируясь или авторизуясь на форуме, Вы соглашаетесь с Политикой конфиденциальности