Mehr

Bestimmen Sie den XY-Versatz in Metern zwischen zwei Breiten-/Längenpunkten (EPSG:4326) und stellen Sie die Punktpositionen mithilfe des XY-Versatzes genau wieder her


Ich habe zwei Tabellen in EPSG:4326, eine für Heimatstandorte und eine für Standortstandorte. Ich muss in der Lage sein, den XY-Versatz in Metern zwischen dem Heimatstandort und den Standortstandorten zu generieren. Ich muss dann in der Lage sein, die Standortstandorte basierend auf dem XY-Versatz vom Ausgangsstandort genau zu regenerieren. Derzeit verwende ich ST_Project, um einen Standort mithilfe des angegebenen XY-Versatzes vom Heimatstandort neu zu erstellen. Die Ergebnisse weichen in Y-Richtung leicht ab. Das Generieren von Linien mit derselben Logik, die zum Berechnen des Offsets verwendet wird, ist genau. Meine Umgebung ist PostgreSQL 9.4.1 PostGIS 2.1.

Das SQL-Skript sind meine Testdaten für dieses Problem. Die Testtabellen für Heim und Standorte sind die beiden Tabellen, die in EPSG:4326 gespeichert sind. Die Site-Tabelle enthält die Felder delta_x und delta_y, die den X- und Y-Versatz in Metern darstellen. Die Ansicht offset_lines enthält Zeilen, die mit einer ähnlichen Logik generiert wurden, wie sie zur Berechnung des Offsets verwendet wurde. Diese Linien erscheinen genau und enden genau an der Stelle wie die Site. Die Ansicht points_using_offsets ist eine Ansicht der Standortpositionen, die unter Verwendung der Offsets von der Ausgangsposition und dem Befehl ST_Project generiert wurden. Diese Orte sind alle leicht in Y-Richtung verschoben.

CREATE TABLE home ( gid integer, geog geography(Point,4326) ); CREATE TABLE Sites ( gid integer, geog geography(Point,4326), delta_x float, delta_y float ); in home-Werte (gid, geog) einfügen (1, ST_MakePoint(-78.9570, 41.6241)::geography); in Sites (gid, geog) Werte einfügen (1,ST_MakePoint(-79.1133, 41.7690)::geography); in Sites (gid, geog) Werte einfügen (2,ST_MakePoint(-78.7726, 41.7801)::geography); in Sites (gid, geog) Werte einfügen (3,ST_MakePoint(-78.7753, 41.4041)::geography); in Sites (gid, geog) Werte einfügen (4,ST_MakePoint(-79.4226, 41.5032)::geography); UPDATE Sites AS st set delta_x = foo.delta_x, delta_y = foo.delta_y FROM ( SELECT CASE WHEN ST_X(s.geog::geometry) < ST_X(h.geog::geometry) THEN ST_Distance_Spheroid(ST_MakePoint(ST_X(h.geog ::geometry), ST_Y(h.geog::geometry) ),ST_MakePoint(ST_X(s.geog::geometry), ST_Y(h.geog::geometry)),'SPHEROID["WGS 84",6378137,298.257223563 ]')*-1 ELSE ST_Distance_Spheroid(ST_MakePoint(ST_X(h.geog::geometry), ST_Y(h.geog::geometry)),ST_MakePoint(ST_X(s.geog::geometry), ST_Y(h.geog: :geometry)),'SPHEROID["WGS 84",6378137,298.257223563]') END AS delta_x, CASE WHEN ST_Y(s.geog::geometry) < ST_Y(h.geog::geometry) THEN ST_Distance_Spheroid(ST_MakePoint(ST_X (s.geog::geometry), ST_Y(s.geog::geometry)),ST_MakePoint(ST_X(s.geog::geometry), ST_Y(h.geog::geometry)),'SPHEROID["WGS 84" ,6378137,298.257223563]')*-1 ELSE ST_Distance_Spheroid(ST_MakePoint(ST_X(s.geog::geometry), ST_Y(s.geog::geometry)),ST_MakePoint(ST_X(s.geog::geometry), ST_Y( h.geog::geometry)),'SPHEROID["WGS 84",6378137,298.257223563]') END AS delt a_y, s.gid FROM home als h, Sites als s) als foo wobei st.gid = foo.gid; CREATE OR REPLACE VIEW offset_lines AS SELECT s.gid as gid, ST_SetSRID(ST_MakeLine(ARRAY[ST_MakePoint(ST_X(h.geog::geometry), ST_Y(h.geog::geometry)),ST_MakePoint(ST_X(s.geog: :geometry), ST_Y(h.geog::geometry)),ST_MakePoint(ST_X(s.geog::geometry), ST_Y(s.geog::geometry))]),4326) als geom FROM home als h, Sites als s; ERSTELLEN ODER ERSETZEN VIEW points_using_offsets AS SELECT CASE WHEN delta_x > 0 and delta_y > 0 THEN ST_Project(ST_Project(h.geog, abs(s.delta_x), Radiant(90)),abs(s.delta_y),radians(0)) WHEN delta_x > 0 und delta_y < 0 THEN ST_Project(ST_Project(h.geog, abs(s.delta_x), Radiant(90)),abs(s.delta_y),Radiant(180)) WHEN delta_x < 0 und delta_y < 0 THEN ST_Project(ST_Project(h.geog, abs(s.delta_x), Radiant(270)),abs(s.delta_y),radians(180)) WHEN delta_x < 0 und delta_y > 0 THEN ST_Project(ST_Project(h.geog , abs(s.delta_x), Radiant(270)),abs(s.delta_y),Radiant(0)) END als geom, s.gid als gid FROM home als h, Seiten als s;

Sie denken kartesisch und arbeiten geodätisch. Wenn Sie wirklich delta_x/delta_y ausführen möchten, führen Sie die Arbeit in Geometrie in einem projizierten Raum aus, nicht in Geographie. Wenn Sie Geografie verwenden möchten, verwenden Sie nicht delta_x/delta_y, verwenden Sie Entfernung/Richtung, die mit ST_Distance(geog,geog) und ST_Azimuth(geog,geog) generiert wurde.

(Es ist manchmal schwer vorstellbar, aber wenn Sie zu einem Punkt direkt westlich von Ihnen gelangen möchten, legen Sie in der Geodätik Ihre Richtung nicht "genau nach Westen" fest. Wenn Sie sich auf der Nordhalbkugel befinden, stellen Sie Ihre Richtung "genau nach Westen und etwas Norden" und wenn Sie im Süden sind, "genau nach Westen und etwas Süden". Je weiter Ihr Zielpunkt entfernt ist, desto ausgeprägter ist der Effekt, bis Sie zu transkontinentalen Flugrouten gelangen. wo Sie über den Pol fliegen können, um zwischen zwei Orten auf demselben Breitengrad zu gelangen. Dies alles, weil die kürzeste Entfernung zwischen zwei Punkten in der Geodätik ein Großkreis ist, der nur den Längen-/Breitenlinien folgt, wenn Ihre beiden Punkte zufällig genau nördlich/südlich voneinander.)