Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Вниз

Перевод из координат экрана в пространство   Найти похожие ветки 

 
Alex_C   (2011-03-28 10:15) [0]

Надо рарисовать на экране глобус.
Для этого пользуюсь известными формулами перевода широты и долготы в XYZ:

function LatLonToXYZ(Lat, Lon: Real ): TPoint3d;
begin
  Result.x := cos(Lat) * sin(Lon);
  Result.y := sin(Lat);
  Result.z := cos(Lat) * cos(Lon);
end;

формулой поворота

function Rotate(alf,bet,gam: real; P: TPoint3d): TPoint3d;
var
 x,y,z,t: real;
begin
 x:=P.x*cos(gam)-P.y*sin(gam);
 y:=P.x*sin(gam)+P.y*cos(gam);
 z:=P.z;

 t:=x*cos(bet)-z*sin(bet);
 z:=x*sin(bet)+z*cos(bet);
 Result.x:=t;

 Result.y:=y*cos(alf)-z*sin(alf);
 Result.z:=y*sin(alf)+z*cos(alf);
end;

и последующего вывода на экран

function TForm1.LatLonToXY(Lat, Lon: extended; var Xout, Yout: longint): boolean;
var
 Point3d: TPoint3d;
begin
 Point3d := Rotate(alfa, beta, 0, LatLonToXYZ(Lat*pi/180, Lon*pi/180) );
 Result := Point3d.z > 0;
 Xout := Center.X + Round(Point3d.x*Radius);
 Yout := Center.Y + Round(Point3d.y*Radius)
end;

все отлично работает - проблем нет.
Однако теперь мне необходимо осуществить обратную задачу - зная координаты мышы на экране пересчитать их в широту и долготу - никак не получается это сделать.


 
oldman ©   (2011-03-28 10:48) [1]


>   Result.x := cos(Lat) * sin(Lon);
>   Result.y := sin(Lat);
>   Result.z := cos(Lat) * cos(Lon);


Lat=arcsin(y)
Lon=arcsin(x/cos(Lat)) или Lon=arccos(z/cos(Lat))


 
OW ©   (2011-03-28 12:16) [2]


> зная координаты мышы на экране пересчитать их в широту и
> долготу - никак не получается это сделать.

а должно?


 
OW ©   (2011-03-28 12:17) [3]

хех..должно..

допустим, у нас проекция на мир сверху, то экранные координаты соотносятся с мировыми, как (x, y, Любое).
т.е. точка по оси z, может быть где угодно

в случае с глобусом (сферой, для определенности) - в двух местах.
(Спицей протыкаем шарик и две точки имеем пересечения)
т.е. где -то в ответе корень квадратный должен быть, т.е. +- Значение.


 
Alex_C   (2011-03-28 13:55) [4]

То oldman: эх если бы все так было просто :) Ты не учитываешь ротацию!


> а должно?


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


 
MBo ©   (2011-03-28 14:35) [5]

1. Проекция из экранных координат на переднюю полусферу (x, y сохраняются, z по ним рассчитывается)
2. Rotate на отрицательные значения alf,bet,gam
3. Перевод в Lat/Lon


 
имя   (2011-03-28 15:04) [6]

Удалено модератором


 
CrytoGen   (2011-03-28 21:18) [7]

Лучше работайте с матрицами, проще будет обратное преобразование сделать.


 
Alex_C   (2011-03-29 16:46) [8]

В общем все оказалось несколько сложнее.
Вот что я сделал:


procedure TForm1.XYToLatLon(alf, bet, gam: Extended; Xin, Yin: longint;
 var Lat, Lon: extended);
var
 Point3d: TPoint3d;
 x, y, z: Extended;
begin
 // Убираем радиус
 Point3d.x := (Xin - Center.X) / Radius;
 Point3d.y := (Yin - Center.Y) / Radius;
 Point3d.z := Sqrt(1 - Sqr(Point3d.x) - Sqr(Point3d.y)); // Формула сферы

 // Вычисляем до поворота
 if alf < 0.0001 then
 begin
   z := Point3d.z;
   y := Point3d.y;
 end
 else if Abs(alf-Pi/2) < 0.0001 then
 begin
   z := -Point3d.y;
   y := Point3d.z;
 end
 else
 begin
   z := (Point3d.z * Cos(alf) - Point3d.y * Sin(alf)) / (Sqr(Cos(alf)) - Sqr(Sin(alf)));
   y := (Point3d.y + z * Sin(alf)) / Cos(alf);
 end;

 if bet < 0.0001 then
 begin
   x := Point3d.x;
 end
 else if Abs(bet-Pi/2) < 0.0001 then
 begin
   x := z;
   z := - Point3d.x;
 end
 else
 begin
   x := (z*Sin(bet) + Point3d.x*Cos(bet)) / (Sqr(Cos(bet)) + Sqr(Sin(bet)));
   z := (z - x*Sin(bet)) / Cos(bet);
 end;

 Point3d.z := z;
 if gam < 0.0001 then
 begin
   Point3d.x := x;
   Point3d.y := y;
 end
 else if Abs(gam-Pi/2) < 0.0001 then
 begin
   Point3d.x := y;
   Point3d.y := -x;
 end
 else
 begin
   Point3d.y := (y * Cos(gam) - x * Sin(gam)) / (Sqr(Cos(gam)) - Sqr(Sin(gam)));
   Point3d.x := (x + Point3d.y * Sin(gam)) / Cos(gam);
 end;

 // Вычисляем широту и долготу
//  if Abs(Point3d.y - Pi/2) > 0.001 then
   Lat := -ArcSin(Point3d.y);
 Lon := ArcSin(Point3d.x / Cos(Lat));
end;


Вроде как работает, но не правильно. Уже и все по нескольку раз проверил...


 
MBo ©   (2011-03-29 19:43) [9]

>Вроде как работает, но не правильно
Значит, отладка нужна.

А вот это что означает?
z := (Point3d.z * Cos(alf) - Point3d.y * Sin(alf)) / (Sqr(Cos(alf)) - Sqr(Sin(alf)));
y := (Point3d.y + z * Sin(alf)) / Cos(alf);


 
Alex_C   (2011-03-30 00:43) [10]


> А вот это что означает?


А вот именно здесь и была ошибка )))
Еще раз внимательно все проверил - после исправления этих двух строк все и заработало)))



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.47 MB
Время: 0.071 c
6-1250966588
Pirog
2009-08-22 22:43
2013.03.22
Page Rank


9-1181473912
@!!ex_
2007-06-10 15:11
2013.03.22
Проблема со стенсилем.


15-1344415193
Дмитрий С
2012-08-08 12:39
2013.03.22
Очередь+Лог (структура таблицы)


15-1348568333
Стьюденд
2012-09-25 14:18
2013.03.22
Подсчет одинаковых слов в Delphi


2-1337119413
TStas
2012-05-16 02:03
2013.03.22
Высота строк в RichEdit е





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский