2015-05-29 19 views
16

Google Maps e MSSQL sembrano essere d'accordo sul modo di calcolare la distanza/lunghezza di una polilinea/linee che usando SRID 4326.Google Maps e lunghezza LINESTRING SQL Server incoerente

MSSQL:

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

Risultato: 9030715.95721209

allora Google Maps:

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

Risultato: 9022896.239500616

In un primo momento ho pensato che fosse solo un diverso raggio di misura terra, così ho suonato in giro con questo e si è rivelato essere più.

Ho bisogno della mia interfaccia JavaScript per abbinare ciò che MSSQL segnalerebbe per rimanere coerente e preciso. Dove o come posso trovare come MSSQL calcola il loro STLength() e può essere replicato in JavaScript?

Aggiornamento:

ho capito se faccio

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

Poi MSSQL restituisce 9022896.23950062

La nuova SRID in MSSQL:

Nuovo “Unità Sphere” Spatial Reference ID Il riferimento spaziale predefinito ID (SRID) in SQL Server 2012 è 432 6, che utilizza il sistema metrico come unità di misura. Questo SRID rappresenta anche la vera forma a sfera ellissoidale della terra . Sebbene questa rappresentazione sia la più accurata, è anche più complessa calcolare la matematica ellissoidale . SQL Server 2012 offre un compromesso in termini di velocità e precisione , aggiungendo un nuovo riferimento spaziale id (SRID), 104001, che utilizza una sfera di raggio 1 per rappresentare una terra perfettamente rotonda.

Quindi il problema è che Google Maps non utilizza una vera sfera ellissoidale nei calcoli. Sto cercando una funzione javascript che ottenga 9030715.95721209 come testimoniato.

ho cercato formula diretta Vincenty qui: http://jsbin.com/noveqoqepa/1/edit?html,js,console e mentre è più vicino non riesco ancora a corrispondere MSSQL

Edit 2:

sono stato in grado di trovare le misure che usa:

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)); 

ma collegare apparentemente quelli in Vincenty non porta fortuna.

+0

L'unica cosa che ho potuto scoprire è che l'asse semi-secondario tende ad essere espresso in altre due cifre decimali, che ha esattamente un'influenza zero sul risultato complessivo. Sinceramente non ho idea di come MSSQL determini la sua distanza. –

+0

Utilizzando il modulo sotto [Esempi live sulle soluzioni Vincenty di geodetiche nella pagina ellissoide] (http://movable-type.co.uk/scripts/latlong-vincenty.html) ottengo 9.030.706.728 m, che è abbastanza vicino a 9030715.95721209 (9 metri su 9x10^9 metri) – geocodezip

+0

Sì, anche questa è la stessa distanza che ho ottenuto usando la soluzione jsbin che ho postato in fondo al mio post. È molto vicino, ma ho bisogno che sia più preciso. – ParoX

risposta

0

L'unico modo per accertarsi è quello di ottenere il programmatore Microsoft al telefono, disassemblare il codice o semplicemente inviare una query a un database di SQL Server e accettarne i risultati.

Questo può essere di aiuto a voi: Using SQL Spatial Types in a .NET Application

Se si vuole provare a smontare, credo che il metodo è nel file Microsoft.SqlServer.Types.dll.

+0

L'opzione 2 sembra più semplice dell'opzione 1. L'opzione 3 non è valida per una soluzione. Qualche consiglio su come smontarlo? Presumo che sia scritto in un linguaggio .NET che è notoriamente pessimo nel prevenire lo smontaggio. – ParoX

+0

Se si sta cercando di far corrispondere ciò che fa SQL Server, suppongo che si stia utilizzando SQL Server nel back-end per qualcos'altro. In caso contrario ... perché ti importa se corrisponde a SQL Server? E se ti stai già connettendo a un server SQL, perché non è fattibile inserire le query sulla geometria nelle procedure su SQL Server o sui servizi Web che eseguono query su SQL Server? –

+0

Sto creando un sistema LRS utilizzando un'interfaccia javascript, ho bisogno di conoscere la distanza di una polilinea circa 10 volte al secondo mentre cambia, questo può essere fatto facilmente con puro javascript (l'ho fatto). Questo non può essere eseguito con una chiamata di back-end a SQL Server perché c'è troppo overhead e invierebbe spam al server. Tuttavia, le distanze che calcola la funzione javascript devono corrispondere al server SQL, altrimenti ci saranno discrepanze tra la vista e il modello. – ParoX

4

Ti rendi conto che Google Maps utilizza Web Mercator, alias EPSG: 3857 e non WGS EPSG: 4326? Il Web Mercator article e i suoi riferimenti possono aiutare a spiegare le differenze.

Provare l'implementazione JavaScript di GeographicLib e/o Proj4js. Come indicato da this question/answer on gis.stackexchange, le implementazioni sottostanti delle conversioni di dati spaziali possono essere sottilmente diverse. Hai almeno bisogno di qualcosa di meglio di Vincenty diretto.

+0

GeographicLib restituisce 9030706.727997527 che è lo stesso della formula di Vincenty. Sto iniziando a pensare che MSSQL non sia accurato ... – ParoX

+0

Puoi usare la formula di Vincenty sul server invece della formula MSSQL? Un altro suggerimento è quello di utilizzare la versione javascript sul client mentre la polilinea cambia e sincronizzare i punti finali della linea con il back-end su un timer o dopo il completamento del disegno. – brenzy

+0

Dato quello che penso possa essere un fraintendimento sulla proiezione utilizzata da Google Maps, potresti voler controllare [linee geodetiche, cerchi, buste in Google Maps] (http://geographiclib.sourceforge.net/scripts/geod-google. html) e le relative istruzioni che possono aiutare a spiegare le differenze che possono spiegare la tua discrepanza. – jwd630

5

Dopo aver esaminato tutte le diverse opzioni, l'opzione migliore sembra essere quella di utilizzare la stessa funzione letterale sia sul server che sul client. Ciò può essere ottenuto in due modi:

Approccio 1: Utilizzare la funzione SQL sul client

In questo caso si potrebbe innescare una query AJAX sul client al server, che a sua volta interroga il database per il calcolo specifico desiderato e restituirlo al cliente.

Approccio 2: Utilizzare la funzione JavaScript in SQL

Questo potrebbe sembrare impossibile, ma usando xp_cmdshell è possibile execute command line commands from sql, ed è possibile eseguire JavaScript dal terminale usando qualcosa come node.js, quindi tutto ciò che si' Resta a sinistra con l'implementazione della funzione Vincenty per essere called from the command line.

La grande domanda qui è come sarà la performance. L'avvio e l'arresto di una istanza di node ogni pochi secondi sembra una cattiva idea, quindi sarebbe molto più ottimale codificare un servizio nel nodo per fare questo lavoro, tuttavia non saprei quale sarebbe il modo migliore per interagire con sql un tale servizio. L'approccio più semplice sarebbe probabilmente per averlo fare una richiesta HTTP a qualcosa di simile localhost:8888/?lat1=&lng1=&etc., ma che sta cominciando ad essere quasi così complesso come approccio 1.

Conclusione

Approccio 1 sembra essere ancora la più ragionevole, anche se l'approccio 2 ti dà molta più flessibilità per fare esattamente quello che vuoi. Per un progetto privato o un progetto perfezionista penso che andrei con l'approccio 2, per un 'dobbiamo finire questo e non abbiamo tempo per sorprese o ottimizzazioni' - un progetto di tipo penso che consiglierei l'approccio numero 1.

+0

Se la precisione non è un problema, allora google maps ha una funzione incorporata e MS SQL SRID 104001 funzionerà come una soluzione che corrisponde abbastanza vicino. Nella mia specifica applicazione, l'accuratezza conta ma sembra che l'approccio 2 sia ciò che è necessario. – ParoX