2015-05-29 6 views
16

Google Maps и MSSQL, кажется, не согласны о том, как рассчитать расстояние/длина ломаной линии/LINESTRING с помощью SRID 4326.Google Maps и длина LINESTRING SQL Server несовместимым

MSSQL:

SELECT geography::STGeomFromText('LINESTRING(-98.78 39.63,2.98 27.52)', 4326).STLength() 

Результат: 9030715.95721209

Тогда Google Maps:

http://jsbin.com/niratiyojo/1/

Результат: 9022896.239500616

Сначала я подумал, что это просто другой радиус измерения земли, так что я играл с этим, и это оказалось больше.

Мне нужен мой интерфейс JavaScript, чтобы он соответствовал тому, что MSSQL будет сообщать, чтобы он был последовательным и точным. Где или как я могу найти, как MSSQL вычисляет их STLength() и может ли он быть реплицирован в JavaScript?

Update:

Я понял, если я

SELECT GEOGRAPHY::STGeomFromText('LINESTRING(-98.78 39.63,2.98 27.52)', 104001).STLength() * 6378137 

Затем MSSQL возвращает 9022896.23950062

Новый SRID в MSSQL:

Новый «Unit Сфера» Spatial Reference ID По умолчанию пространственная ссылка ID (SRID) в SQL Server 2012 - 432 6, который использует метрическую систему как свою единицу измерения. Этот SRID также представляет истинную форму эллипсоидальной сферы Земли . Хотя это представление является наиболее точным, также сложнее рассчитать точную эллипсоидальную математику . SQL Server 2012 предлагает компромисс в скорости и точность , добавив новый пространственный ссылочный идентификатор (SRID), 104001, который использует сферу радиуса 1 для представления совершенно круглой земли.

Таким образом, проблема заключается в том, что Google Maps не использует истинную эллипсоидальную сферу в расчетах. Я ищу функцию javascript, которая получает 9030715.95721209 в качестве свидетеля.

Я попробовал прямую формулу Vincenty здесь: http://jsbin.com/noveqoqepa/1/edit?html,js,console и в то время как это ближе я до сих пор не может сравниться с MSSQL

Edit 2:

я смог найти измерения, которые он использует:

SridList._sridList.Add(4326, new SridInfo(4326, "EPSG", 4326, "GEOGCS[\"WGS 84\", DATUM[\"World Geodetic System 1984\", ELLIPSOID[\"WGS 84\", 6378137, 298.257223563]], PRIMEM[\"Greenwich\", 0], UNIT[\"Degree\", 0.0174532925199433]]", "metre", 1.0, 6378137.0, 
6356752.314)); 

но казалось бы, вставляя их в Винченти, не повезло.

+0

Единственное, что я смог выяснить, это то, что полуосновная ось имеет тенденцию выражаться еще двумя десятичными знаками, что имеет ровно нулевое влияние на общий результат. Я искренне не знаю, как MSSQL определяет расстояние. –

+0

Используя форму в [Live примеры на решениях Vincenty геодезических на странице эллипсоида] (http://movable-type.co.uk/scripts/latlong-vincenty.html), я получаю 9 030 706 728 м, что довольно близко к 9030715.95721209 (9 метров из 9x10^9 метров) – geocodezip

+0

Да, это то же самое расстояние, которое я получил с помощью решения jsbin, которое я разместил в нижней части сообщения. Это очень близко, но мне нужно, чтобы это было точнее. – ParoX

ответ

0

Единственный способ, которым вы можете быть уверенным, - это получить программу-программист Microsoft по телефону, разобрать код или просто отправить запрос в базу данных SQL Server и принять его результаты.

Это может оказаться полезным для вас: Using SQL Spatial Types in a .NET Application

Если вы хотите попробовать свои силы в разборке, я считаю, что метод в файле Microsoft.SqlServer.Types.dll.

+0

Вариант 2 кажется проще, чем вариант 1. Вариант 3 не подходит для решения. Какие-либо рекомендации по его демонтажу? Я предполагаю, что он написан на языке .NET, который, как известно, плохо предотвращает разборку. – ParoX

+0

Если вы пытаетесь сопоставить то, что делает SQL Server, я предполагаю, что вы используете SQL Server в конце для чего-то другого. Если нет ... почему вам все равно, соответствует ли он SQL Server? И если вы уже подключаетесь к SQL Server, почему нецелесообразно размещать ваши геометрические запросы в процедурах SQL Server или веб-служб, которые запрашивают SQL Server? –

+0

Я создаю систему LRS, используя интерфейс javascript, мне нужно знать расстояние от полилинии примерно 10 раз в секунду по мере ее изменения, это можно сделать с помощью чистого javascript (я это сделал). Этого нельзя сделать с помощью внутреннего вызова SQL Server, потому что слишком много накладных расходов и спам сервера. Однако расстояния, которые вычисляет функция javascript, должны соответствовать SQL-серверу, иначе будут наблюдаться расхождения между представлением и моделью. – ParoX

4

Вы понимаете, что в Google Maps используется веб-Меркатор, иначе EPSG: 3857, а не WGS EPSG: 4326? Web Mercator article и его ссылки могут помочь объяснить различия.

Попробуйте выполнить JavaScript в GeographicLib и/или Proj4js. Как указывается this question/answer on gis.stackexchange, базовые реализации преобразований пространственных данных могут быть несколько разными. Вам, по крайней мере, нужно что-то лучше, чем Винценти.

+0

GeographicLib возвращает 9030706.727997527, что совпадает с формулой Vincenty. Я начинаю думать, что MSSQL неточен ... – ParoX

+0

Можете ли вы использовать формулу Vincenty на сервере вместо формулы MSSQL? Другое предложение - использовать версию javascript на клиенте по мере изменения полилинии и синхронизировать конечные точки линии с задним концом либо по таймеру, либо по завершении чертежа. – brenzy

+0

Учитывая, что я думаю, что это неправильное понимание проекции, используемой Google Maps, вы можете проверить [Геодезические линии, круги, конверты в Картах Google] (http://geographiclib.sourceforge.net/scripts/geod-google. html) и соответствующие инструкции, которые могут помочь объяснить различия, которые могут объяснять ваше несоответствие. – jwd630

5

Пройдя через все различные варианты, лучшим вариантом является использование одной и той же функции буквально как на сервере, так и на клиенте. Это может быть достигнуто двумя способами:

подход 1: Используйте функцию SQL на клиенте

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

подход 2: Используйте функцию Javascript в SQL

Это может показаться совершенно невозможно, но с помощью xp_cmdshell это можно execute command line commands from sql, и вы можете запустить JavaScript из терминала, используя что-то вроде node.js, поэтому все, что вы» re left with реализует функцию Vincenty как called from the command line.

Большой вопрос: как это будет? Запуск и остановка экземпляра node каждые несколько секунд кажется относительно плохой идеей, поэтому было бы гораздо более оптимальным кодировать службу в узле для выполнения этой работы, однако я бы не знал, что лучший способ для sql взаимодействовать с такой услуги. Самый простой подход, вероятно, будет иметь это сделать запрос HTTP, чтобы что-то вроде localhost:8888/?lat1=&lng1=&etc., но это начинает быть столь же сложным, как подход 1.

Заключение

подход 1 по-прежнему, как представляется, наиболее разумным, хотя подход 2 дает вам гораздо большую гибкость, чтобы делать именно то, что вы хотите. Для частного проекта или проекта перфекционистов я думаю, что я бы пошел с подходом 2, потому что «нам нужно закончить это, и у нас нет времени для сюрпризов или оптимизаций». Я бы посоветовал подход № 1.

+0

Если точность не является проблемой, то встроенные функции google maps и MS SQL SRID 104001 будут работать как решение, которое будет достаточно близко. В моем конкретном приложении точность имеет значение, но кажется, что подход 2 может быть тем, что необходимо. – ParoX