Shapefile PRJ zur PostGIS SRID Nachschlagetabelle?

38

Ich habe mich gefragt, ob es eine Shapefile-PRJ für die PostGIS-SRID-Nachschlagetabelle gibt. Etwas, das die gängigsten Shapefile-PRJ-Definitionen in die wahrscheinliche SRID übersetzen kann.

Wenn Sie mit PostGIS und pgAdminIII Ihre Shapefiles mit postgisgui importieren, bleibt die SRID "-1". Anscheinend sollte das Tool in der Lage sein, den Esri PRJ zu analysieren und die richtige (oder zumindest einige Optionen) SRID zu bestimmen, anstatt nur die Standardeinstellung beizubehalten.

Oder hat der Importeur die Möglichkeit, sofort neu zu projizieren, wenn Sie eine andere SRID wählen?

Es mag mir faul vorkommen, aber ich finde es merkwürdig, dass diese Funktion noch nicht eingerichtet wurde. Weiß jemand, ob dieses Konzept in Arbeit ist oder aus gutem Grund, warum es weggelassen wurde?

RyanDalton
quelle

Antworten:

9

Ausgeliehen von der Idee von @iant ist hier ein PL / Python3-Modul, das die EPSG-SRID-Ganzzahlcodes aus einer PRJ-Datei über den Webdienst http://prj2epsg.org abruft .

Installieren Sie zunächst PL / Python3:

CREATE LANGUAGE plpython3u;

Fügen Sie nun die SQL-Funktion hinzu, deren Code für Python 3 geschrieben wurde:

CREATE OR REPLACE FUNCTION prj2epsg(prj_file text) RETURNS integer AS
$BODY$

import json
from urllib.parse import urlencode
from urllib.request import urlopen

with open(prj_file, 'r') as fp:
    prj_txt = fp.read()

query = urlencode({
    'exact': True,
    'error': True,
    'mode': 'wkt',
    'terms': prj_txt})

webres = urlopen('http://prj2epsg.org/search.json', query.encode())
jres = json.loads(webres.read().decode())

return int(jres['codes'][0]['code'])

$BODY$ LANGUAGE plpython3u VOLATILE COST 100;

So verwenden Sie es von PostgreSQL aus:

SELECT prj2epsg(E'C:\\Temp\\countries.prj');

gibt 4326 für mein Test-Shapefile zurück.

Mike T
quelle
Ich werde dies als die Lösung markieren. Während die anderen alle ausgezeichnet sind, liebe ich diese Idee. Wenn wir jetzt nur jemanden mit der Codierungsfähigkeit dazu bringen können, diese Art von Funktionalität in den pgAdmin PostGIS-Shapefile-Loader aufzunehmen, so dass er beim Lesen des SHP automatisch die richtige SRID ermittelt. Ich drücke die Daumen.
RyanDalton
1
Die Einschränkung besteht natürlich darin, dass eine Internetverbindung erforderlich ist und ein externer Webdienst zum Laufen gebracht werden muss.
Mike T
57

GDAL hat eine schöne und bequeme Schnittstelle zur PROJ4-Bibliothek.

Wenn Sie mit Python vertraut sind und die GDAL-Python-Bindungen verwenden, haben Sie beim Importieren der osr-Klassen sehr bequeme Methoden zum Lesen und Exportieren von Projektionsdarstellungen in eine Vielzahl von Formaten wie PROJ4, WKT, Esri .PRJ.

Zum Beispiel konvertiert dieses Skript Ihre .PRJ-Datei Ihres Shapefiles in WKT und PROJ4 (die letzte wird von PostGIS verwendet):

#! /usr/bin/env python

import sys
from osgeo import osr

def esriprj2standards(shapeprj_path):
   prj_file = open(shapeprj_path, 'r')
   prj_txt = prj_file.read()
   srs = osr.SpatialReference()
   srs.ImportFromESRI([prj_txt])
   print 'Shape prj is: %s' % prj_txt
   print 'WKT is: %s' % srs.ExportToWkt()
   print 'Proj4 is: %s' % srs.ExportToProj4()
   srs.AutoIdentifyEPSG()
   print 'EPSG is: %s' % srs.GetAuthorityCode(None)

esriprj2standards(sys.argv[1])

Führen Sie dies in der Befehlszeile aus:

$ python esriprj2standards.py /home/pcorti/data/shapefile/country.prj 
Shape prj is: GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
WKT is: GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
Proj4 is: +proj=longlat +datum=WGS84 +no_defs 
EPSG is: 4326
capooti
quelle
Bei diesem Ansatz sind zwei Probleme aufgetreten: (1) +proj=longlat +datum=WGS84 +no_defsist nicht in der spatial_ref_sysTabelle enthalten, sodass Sie die Ausgabe nicht zum Nachschlagen der SRID verwenden können. und (2) Ich kann scheinbar keine SRID-Eigenschaft oder -Methode finden (es gibt eine praktische ImportFromEPSG(SRID)Methode, aber nicht umgekehrt)
Mike T
4
Ich habe das Skript mit einem Aufruf der AutoIdentifyEPSG () -Methode aktualisiert, die die Magie machen wird;)
capooti
Sehr cool. Ausgezeichnete Arbeit!
RyanDalton
Wann gdalsrsinfound ogrinfoscheitern Sie, das ist der Weg zu gehen!
kontextify
Beachten Sie, dass srs.GetAuthorityCode(None)möglicherweise immer noch keine zurückgegeben wird, wenn keine enge SRID identifiziert wurde.
Astrojuanlu
19

Es ist schon eine Weile her, dass ich POSTGIS-Srids verwendet habe, aber wenn es sich nur um EPSG-Codes handelt, können Sie sie mit http://prj2epsg.org/search aus (defekten) ESRI.prj-Dateien nachschlagen.

Ian Turton
quelle
Dies ist eine wirklich clevere Website. Mit Blick auf die API könnten Sie ein nettes serverseitiges Skript schreiben, um den Vorgang zu automatisieren.
Mike T
4

Als Mischung aus Lösungen habe ich ein Skript erstellt, mit dem ich beliebige Shapefiles in Postgis laden kann. Es wird auch versucht, die Codierung des DBF zu erkennen.

from chardet.universaldetector import UniversalDetector
import os.path
import sys
import dbfUtils
import sys
from osgeo import osr
from urllib import urlencode
from urllib2 import urlopen
import json

shp_file = sys.argv[1]
dbf_file = shp_file[0:-4] + '.dbf'
prj_file = shp_file[0:-4] + '.prj'

#Try detecting the SRID, by default we set to 4326 and hope the best
srid=4326
if os.path.isfile(prj_file):
    prj_filef = open(prj_file, 'r')
    prj_txt = prj_filef.read()
    prj_filef.close()
    srs = osr.SpatialReference()
    srs.ImportFromESRI([prj_txt])
    srs.AutoIdentifyEPSG()
    code = srs.GetAuthorityCode(None)
    if code:
        srid= code
    else:
        #Ok, no luck, lets try with the OpenGeo service
        query = urlencode({
            'exact' : True,
            'error' : True,
            'mode' : 'wkt',
            'terms' : prj_txt})
        webres = urlopen('http://prj2epsg.org/search.json', query)
        jres = json.loads(webres.read())
        if jres['codes']:
            srid = int(jres['codes'][0]['code'])

#Try to detect the encoding
dbf = open(dbf_file, 'rb')
db = dbfUtils.dbfreader(dbf)

detector = UniversalDetector()
for row in db:
    detector.feed(str(row))
    if detector.done: break
detector.close()
dbf.close()

encoding = detector.result["encoding"]
if encoding=="ascii":
    encoding="LATIN1"

print "shp2pgsql -s %s -k -i -I -W %s %s.shp public.importing_table" %(srid,encoding,shp_file)
Jatorre
quelle
3

srsly. Ich will auch eins.

Viele Leute scheinen sie auf http://spatialreference.org nachzuschlagen

Wenn Sie Shapefiles mit PostGIS (und dem PostGIS-Loader für PGAdmin) importieren, werden die Projektinformationen in einer Tabelle namens "spatial_ref_sys" nachgeschlagen.

Soweit ich weiß, enthält die mit PostGIS gepackte Standardtabelle "spatial_ref_sys" nur OGC WKT-Darstellungen (Open Geospatial Consortium Well Known Text) einiger räumlicher Bezugssysteme und NICHT der räumlichen Bezugssysteme von ESRI.

Aus der PostGIS 1.5.2-Dokumentation:>

Die spatial_ref_sys-Tabelle ist eine in PostGIS enthaltene und OGC-konforme Datenbanktabelle, in der über 3001 bekannte räumliche Bezugssysteme und Details aufgelistet sind, die für die Transformation / Neuprojektion zwischen ihnen erforderlich sind.

Obwohl die PostGIS-Tabelle "spatial_ref_sys" über 3000 der am häufigsten verwendeten Raumbezugssystemdefinitionen enthält, die von der proj-Bibliothek verarbeitet werden können, enthält sie nicht alle dem Menschen bekannten und Sie können sogar Ihre eigene benutzerdefinierte Projektion definieren, wenn Sie mit proj4-Konstrukten vertraut sind . Beachten Sie, dass die meisten räumlichen Bezugssysteme regional sind und keine Bedeutung haben, wenn sie außerhalb der Grenzen verwendet werden, für die sie vorgesehen sind.

Eine ausgezeichnete Ressource zum Auffinden von räumlichen Bezugssystemen, die nicht im Kernsatz definiert sind, ist http://spatialreference.org/. Einige der am häufigsten verwendeten räumlichen Bezugssysteme sind: 4326 - WGS 84 Long Lat, 4269 - NAD 83 Long Lat, 3395 - WGS 84 World Mercator, 2163 - US National Atlas Equal Area, Raumbezugssysteme für jeden NAD 83, WGS 84 UTM-Zone - UTM-Zonen sind eine der idealsten Messzonen, decken jedoch nur 6-Grad-Regionen ab.

Verschiedene räumliche Bezugssysteme auf der Ebene des US-Bundesstaates (meter- oder fußbasiert) - in der Regel eines oder zwei pro US-Bundesstaat. Die meisten Messgeräte befinden sich im Core-Set, aber viele der fußbasierten oder von ESRI erstellten Geräte müssen von Spatialreference.org abgerufen werden.

Allerdings enthält ogr2ogr ESRI- Raumreferenzsysteme , wie ich kürzlich durch die Großzügigkeit anderer gelernt habe.

Sowohl in ogr2ogr als auch in spatial_ref_sys wird der in der .proj-Datei enthaltene Text anscheinend mit einer Tabelle von OGC WKT verglichen. Dabei handelt es sich um ein geringfügig anderes Textformat als das in einer .proj-Datei häufig vorkommende ESRI WKT-Format. Ich bin mir auch nicht sicher, wie PostGIS die einzelnen SRS sucht, aber die kleinen Unterschiede zwischen ESRI WKT und OGC WKT können zu fehlgeschlagenen Übereinstimmungen führen.

Es scheint einfach zu sein, räumliche ESRI-Referenzsysteme an die Standardtabelle "spatial_ref_sys" in PostGIS anzuhängen. Vielleicht hat jemand schon einen Patch oder ein Skript.

Ich könnte mich irren, weil ich gerade in den letzten Tagen darauf gestoßen bin, und ich war mit der gleichen Sache frustriert. Vielleicht kennt jemand anderes eine großartige Ressource?

BenjaminGolder
quelle
1

Es ist schon eine Weile her, dass ich musste, aber, wie ich mich erinnere, gibt Ihnen http://spatialreference.org/ nicht nur die Möglichkeit zu suchen , sondern auch die Möglichkeit, eine prj-Datei hochzuladen.

Dann erhalten Sie als eine der Ausgabeoptionen das entsprechende Postgis-Insert zum Einfügen in die Spatial_ref_sys-Tabelle.

Für die Einfügeanweisung, die es gibt, ersetze ich das generierte srid, das es erstellt, durch das EPSG oder ESRI. Wenn Sie eine Primärschlüsselverletzung feststellen, wissen Sie höchstwahrscheinlich, dass diese bereits in der Tabelle enthalten ist.

LR1234567
quelle