Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2013.03.22;
Скачать: CL | DM;

Вниз

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

 
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;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.074 c
15-1330604387
upc
2012-03-01 16:19
2013.03.22
Покупка Delphi


4-1258417192
мурзик
2009-11-17 03:19
2013.03.22
Как определить что за изменения произошли в директории?


15-1331018645
Unknown user
2012-03-06 11:24
2013.03.22
TStringList.AddObject добавление строки вместо TObject


2-1347507525
turbo
2012-09-13 07:38
2013.03.22
Как перевести дату в нормальный формат?


15-1353580932
NieL
2012-11-22 14:42
2013.03.22
Настройки программы