Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 1.0/2.0 (http://www.flasher.ru/forum/forumdisplay.php?f=93)
-   -   Определение расстояния на карте (http://www.flasher.ru/forum/showthread.php?t=117034)

Division 17.10.2008 00:32

Определение расстояния на карте
 
Привет. Мне нужно сделать что-то вроде этого: http://www.yourcharter.ru/map/
То есть имеется географическая карта. Мы указываем две точки и получаем расстояние в километрах. Вообщем-то всё уже готово за исключением корректного определения расстояния по карте. Я сначала думал, что это будет просто, но выяснилось что таки нет. То есть по идее нужно взять расстояние в пикселях и умножить на масштаб, но на деле так не получается. Все карты которые я смог найти имеют не постоянный масштаб. То есть к примеру если 100 пикселей в одном месте карты равны 1000 км, то в другом месте карты 100 пикселей могут быть равны 1700 км. Так что такой вариант не проходит. Как можно померять расстояние по такой карте? Кто-то сталкивался с подобными задачами? Может быть есть карты с постоянным масштабом?
Пока что единственная идея - использовать меркаторскую проекцию, приводить экранные координаты к географическим, а по географическим уже считать расстояние. ИМХО не лучший вариант. Помогите плиз. Спасибо.

Infectedcell 17.10.2008 10:18

а что мешает воспользоваться нормальной картой с обозначенный масштабом 1:..., перерисовать в кривые (если надо)
и использовать именно её. Ну и далее уже производить расчет...

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

Division 17.10.2008 11:08

Здесь как раз выскакивают мои пробелы знаний в географии. Какая карта подойдёт в данном случае? Я смотрел инфу по разным картографическим проекциям и так и не смог найти проекцию, при котором длины бы не искажались, а масштаб оставался постоянным. Мне не требуется учитывать дороги, просто расстояние по прямой(на самом деле по дуге большого круга).
Если можно - дай ссылку на нормальную карту, хоть посмотрю как они выглядят.
PS вообще мне нужны крупномасштабные карты Евразии или мира. На мелкомасштабных картах ИМХО неточность измерения можно и не заметить.
UPD, да, в флешке с примером они же как-то определяют расстояние. И карта у них тоже с не постоянным масштабом (можно приложить ручку к монитору в одном месте карты, померять, повторить то же самое в другом месте и результат будет разный).
Цитата:

картой с обозначенный масштабом 1:...
Как я понял, это указывается масштаб по какой-то параллели, например, по экватору. И на этой параллели он остаётся постоянным.

Infectedcell 17.10.2008 13:06

Цитата:

Сообщение от Division (Сообщение 770951)
Как я понял, это указывается масштаб по какой-то параллели, например, по экватору. И на этой параллели он остаётся постоянным.

если не изменяет память... [в одним сантиметре : Н километров]

Карт полно...
Google

†‡Paladin‡† 17.10.2008 13:34

Класс не очень точен, но для больших карт (и даже для масштаба города) вполне подходит.
Код:

package fzn7.utils
{
        public class GeoUtil extends Object
        {

        /**
        * Helper function
        * */
        static private function deg2rad(degrees:Number):Number {
            var retVal:Number = degrees * Math.PI / 180;
            return retVal;
        }

        /**
        * Helper function
        * */
        static private function rad2deg(radians:Number):Number {
            var retVal:Number = radians * 180 / Math.PI;
            return retVal;
        }

        /**
        * Function finds distance between 2 geo points.
        * */
        static public function getDistance(lat1:Number, lon1:Number, lat2:Number, lon2:Number, units:String = "K"): Number {
            var distance:Number = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) +
                                                        Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
                                                            Math.cos(deg2rad(lon1 - lon2));
                                                           
            distance = Math.acos(distance);
            distance = rad2deg(distance);
           
            var retVal:Number = distance * 60 * 1.1515;
           
            units = units.toUpperCase();
            if (units == "K")
            {
                return retVal * 1.60934;
            }
            if (units == "N")
            {
                return retVal * 0.8684;
            }
            return undefined;
        }
    }
}


Division 17.10.2008 13:45

Цитата:

если не изменяет память... [в одним сантиметре : Н километров]
Ну и к чему это? Я же сказал, что масштаб как правило не постоянный. То есть тупо взять линейку и начать мерять нельзя(по крайней мере на картах которые я смотрел) Те же карты от google maps имеют равнопромежуточную проекцию, которая тоже искажает длины. Хотелось бы узнать, есть ли карты с постоянным масштабом, которые можно мерять линейкой? Или как тогда измерять расстояние по картам?
Цитата:

Карт полно...
Google
Карт конечно полно, но учитывая описанные выше проблемы, всё не так просто.
UPD: †‡Paladin‡†, спасибо, посмотрю
UPD2: †‡Paladin‡†, здесь я так понял, требуется для начала пребразовать экранные координаты в географические? Такой метод я описывал в первом посте. Вообще по идее надо ещё учитывать наименование широты и долготы (СШ/ЮШ или ЗД/ВД) и в зависимости от неё выбирать знак числа, который передать в твой метод getDistance . Не помнишь как?

chingachgoog 17.10.2008 15:20

Если карта ТОПОГРАФИЧЕСКАЯ, т.е. крупномасштабная, то мерить расстояние легко и просто - так же как линейкой на распечатке этой карты. Разумеется в любом случае надо знать масштаб.
Но если речь о длине большого круга и более мелком масштабе - то тут совсем другая история. Придется рисовать сетку координат, и уже по координатам (долгота/широта) рассчитывать расстояния. Я вот так делал похожую задачу:
http://flasher.ru/forum/showthread.php?t=103787

†‡Paladin‡† 17.10.2008 15:43

Цитата:

Сообщение от Division (Сообщение 770976)
UPD2: †‡Paladin‡†, здесь я так понял, требуется для начала пребразовать экранные координаты в географические? Такой метод я описывал в первом посте. Вообще по идее надо ещё учитывать наименование широты и долготы (СШ/ЮШ или ЗД/ВД) и в зависимости от неё выбирать знак числа, который передать в твой метод getDistance . Не помнишь как?

Да это класс для расчета расстояния между географическими координатами. Просто находит расстояние между двумя точками на сфере.
Я его юзал при работе с yahoo maps, что-бы не бегать к ним на сервер для расчета расстояния. К счастью ихний API сам отдает правильною широту и долготу.

dantist86 20.10.2008 20:11

http://mainmaps.com/fly - старушка, еще на Flash MX. С точки зрения флеш-проекта - мягко скажем слабенько. Но расстояния считает четко. Договаривайся, я там уже не работаю.:)

Division 20.10.2008 20:25

Всем спасибо, сделал(почти, жду пока дизайнер карту подготовит) определением расстояния по географическим координатам.
dantist86, что-то мне подсказывает, что раз уж меркаторская проекция, то сделано тем же способом что и у меня. Кстати, до сих пор не могу представить как можно получить из экранных координат географические на проекциях, где параллели не перпендикулярны меридианам.

Вот код мегакласса с комментариями (: Может кому-то когда-то пригодится.
Код:

/*

  Мегакласс для определения расстояний между
  точками на поверхности земли

*/

class Distance {

        public static var R = 6371; // Радиус Земли в км
       
        // Входные данные в градусах
        // Знаки должны быть такие:
        //        СШ +
        //        ЮШ -
        //        ВД +
        //        ЗД -
        public static function GetDistance(lat1, lon1, lat2, lon2) : Number {
                // Переводим в радианы
                lon1 *= Math.PI/180; // Долгота
                lat1 *= Math.PI/180; // Широта
                lon2 *= Math.PI/180;
                lat2 *= Math.PI/180;
               
                var cosd = Math.sin(lat1)*Math.sin(lat2)+Math.cos(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2);
                var d = Math.acos(cosd);
               
                var L = d*R; // Расстояние в км
               
                return L;
        }
       
}

Использовал только данные отсюда

dantist86 20.10.2008 20:34

Division, твои формулы предполагают, что Земной шар - правильный шар. Это несколько не верно - Земля эллипсоид. На больших расстояниях будут ошибки. Например от Лондона до Сиднея существенные. Хотя не знаю, какая точность вам нужна.

Division 20.10.2008 20:39

Да, это я знаю. Я буду только Евразию мерять, так что думаю мне хватит. А вообще, есть где почитать как достичь более высокой точности?

chingachgoog 20.10.2008 20:57

Цитата:

Сообщение от dantist86 (Сообщение 771673)
Division, твои формулы предполагают, что Земной шар - правильный шар. Это несколько не верно - Земля эллипсоид. На больших расстояниях будут ошибки. Например от Лондона до Сиднея существенные. Хотя не знаю, какая точность вам нужна.

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

dantist86 20.10.2008 21:24

Division, нашел в своих архивах ссылку http://www.posc.org/Epicentre.2_2/Da...e/eu_cs34.html
chingachgoog, я к сожалению отошел от картографической тематики и что-то не тянет возвращаться. Сорри.:)

Division 21.10.2008 11:06

dantist86, спасибо, почитаю. Ещё вопрос. Я тут вдруг понял, что опять провтыкал. На этот раз с приведением экранных координат в географические. Значит, использую меркаторскую проекцию. С долготой всё понятно, на карте нарисованы меридианы мы можем посмотреть между какими двумя значениями находится точка и интерполицией получить значение долготы. Но вот с широтой так уже не пройдёт. Может подскажешь, как мне получить долготу из координаты Y курсора мыши, если я знаю координату Y двух ближайших широт? Например, курсор находится между 45 СШ и 60 СШ (координаты Y курсора, 45 СШ и 60 СШ мы знаем).

Надеюсь я нормально сформулировал. Буду и сам пытатся разобраться, но любой помощи благодарен.

Вообщем, кажется таки сделал. Спасибо википедии. Пока что только в excel, но работает должным образом. Может кому понадобится, так что напишу как сделал. Значит, чтобы найти широту по экранной координате Y на меркаторской проекции надо воспользоваться такой формулой:
Код:

φ = 2*arctg(exp(Y/C))-Pi/2
Где φ - искомая широта, Y - координата Y курсора, C - некая константа.
C я нашёл таким образом:
Код:

C = X/долгота
Допустим, будем мерять от 0 до 15 градусов восточной долготы.
X - это расстояние в пикселях от 0 до 15 градусов ВД.
Долгота в нашем случае 15. Нужно перевести в радианы перед подстановкой.


Часовой пояс GMT +4, время: 09:11.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.