Teil 1 Wenn Sie auf die Schaltfläche im Plug-In klicken Ich habe ein Plug-In erstellt, mit dem die Koordinaten der EPSG: 4301-Multipolygon-Ebene in EPSG: 4612 konvertiert werden können.
Es ist jedoch nur für Multi-Polygon-Ebenen nutzlos. Da es keine Schichten im ebenen orthogonalen Koordinatensystem unterstützt Dieses Mal möchte ich diesen Bereich stärken und etwas praktischer gestalten.
・ Alle Geometrietypen können konvertiert werden ・ Kann unabhängig von Breite / Länge und Ebenenwinkel konvertiert werden Es kann eine Nachkonvertierungsschicht erstellt werden, die den Attributwert erbt. ~~ ・ Sie können mehrere Ebenen auswählen und gleichzeitig konvertieren ~~ ・ Behandeln Sie keine Ausnahmen
Da das Konvertieren mehrerer Ebenen gleichzeitig eine Frage der Benutzeroberfläche ist, habe ich beschlossen, sie zu trennen. Geben wir unser Bestes.
・ Vorwärtskonvertierung (japanisches Geografiesystem → Weltgeografiesystem) Was Sie tun können (fertig) </ font> ・ Kann unabhängig von Breite / Länge und Ebenenwinkel konvertiert werden ・ Alle Geometrietypen können konvertiert werden Es kann eine Nachkonvertierungsschicht erstellt werden, die den Attributwert erbt. ・ Interpolieren Sie den Korrekturwert der Parameterdatei, um die Genauigkeit zu verbessern. * Schwierigkeitsgrad: Mittel ・ Es können mehrere Ebenen gleichzeitig ausgewählt und konvertiert werden ・ Reverse Conversion (Weltvermessungssystem → Japanisches Vermessungssystem) ist ebenfalls möglich. * Schwierigkeitsgrad: Hoch
Wenn Sie die Quelle nicht in Teil 1 erstellt haben, löschen Sie sie aus dem Repository. https://github.com/ozo360/tky2jgd/releases/tag/ddbc2ba
Ich sage nicht, dass es allen entspricht. Der Geometrietyp der Vektorebene, die QGIS verarbeiten kann, ist QgsWkbTypes ::ometryType. Ein anderer Typ ist QgsWkbTypes :: Type.
Das Ziel dieses Plug-Ins ist auf 2D-Daten mit Punkten, Linien und Polygonen beschränkt. Dies sollte die meisten Daten abdecken. Ich weiß nicht, ob es mit Kurven- und Dreiecksdaten richtig konvertiert werden kann, daher werde ich es nach dem Erstellen testen. Wenn es nicht funktioniert, ändern Sie es, um es auszuschließen.
Gehen Sie wie folgt vor, um die Konvertierungsquellenebene wkbType abzurufen und in die URL der neuen Ebene einzubetten. Die Ausnahmeverarbeitung wird nicht ausgeführt, aber ein Zweig ist enthalten, um das Ziel zu begrenzen.
layer = self.iface.activeLayer()
wkbType = layer.wkbType()
#Ziellinienpolygon
if not QgsWkbTypes.geometryType(wkbType) in [
QgsWkbTypes.PointGeometry,
QgsWkbTypes.LineGeometry,
QgsWkbTypes.PolygonGeometry]:
#Nicht zutreffender GeometryType
self.iface.messageBar().pushMessage("tky2jgd <b>{}</b>".format('activeLayer is out of scope geometryType'), Qgis.Warning)
#Targeting von 2D-Ebenen
if QgsWkbTypes.hasZ(wkbType) or QgsWkbTypes.hasM(wkbType):
#Nicht zutreffend wkbType
self.iface.messageBar().pushMessage("tky2jgd <b>{}</b>".format('activeLayer is out of scope wkbType'), Qgis.Warning)
self.wkbType = QgsWkbTypes.displayString(wkbType)
layerUri = self.wkbType +"?crs=postgis:4612"
newlayer = QgsVectorLayer(layerUri, "exchange", "memory")
Ich habe lange gebraucht, weil ich nicht wusste, wie ich die Enum-Zeichenfolge (displayString) erhalten soll, aber ich habe es geschafft, eine Ebene zu erstellen, die dem Geometrietyp der Zielebene entspricht.
Da das Ziel das japanische geodätische System ist, müssen die folgenden Konvertierungen durchgeführt werden können.
System | Konvertierungsquelle SRID | SRID des Konvertierungsziels |
---|---|---|
4301 | 4612 | |
I | 30161 | 2443 |
II | 30162 | 2444 |
III | 30163 | 2445 |
IV | 30164 | 2446 |
・ | ・ | ・ |
・ | ・ | ・ |
・ | ・ | ・ |
XVIII | 30178 | 2460 |
XIX | 30179 | 2461 |
Außerdem zeigt die Parameterdatei den Korrekturwert in EPSG: 4301. Der rechte Winkel der Ebene muss in Breiten- und Längengrade konvertiert werden, bevor der Korrekturwert verschoben wird. Daher erfolgt die Konvertierung in die Konvertierungsziel-SRID von EPSG: 4301 für jede SRID. Generieren Sie jeweils eine Koordinatenkonvertierungsklasse.
layer = self.iface.activeLayer()
srid = layer.crs().postgisSrid()
if srid == 4301:
self.isLonlat = True
self.toSrid = 4612
elif (srid > 30160 and srid < 30180):
self.isLonlat = False
self.toSrid = 2442 + srid - 30160
else:
#Nicht zutreffende SRID
self.iface.messageBar().pushMessage("tky2jgd <b>{}</b>".format('activeLayer is not Tokyo Datum'), Qgis.Warning)
#Generieren Sie eine Koordinatentransformationsklasse
crs4301 = QgsCoordinateReferenceSystem(4301, QgsCoordinateReferenceSystem.EpsgCrsId)
if not self.isLonlat:
crsFrom = QgsCoordinateReferenceSystem(fromSrid, QgsCoordinateReferenceSystem.EpsgCrsId)
self.trans4301 = QgsCoordinateTransform(crsFrom, crs4301, QgsProject.instance())
crsTo = QgsCoordinateReferenceSystem(self.toSrid, QgsCoordinateReferenceSystem.EpsgCrsId)
self.transTo = QgsCoordinateTransform(crs4301, crsTo, QgsProject.instance())
Solange Sie eine Koordinatenkonvertierungsklasse haben und diese zum Zeitpunkt der Konvertierungsverarbeitung orthogonal ist, müssen Sie nur eine Vorverarbeitung durchführen, um sie in Breiten- und Längengrade zu konvertieren.
Sie müssen der neuen Ebene eine Spalte hinzufügen, um die Attributwerte zu erben. Kopieren Sie die Spalten von der ursprünglichen Ebene in die neue Ebene.
#Wenn newLayer eine neue Ebene ist
layer = self.iface.activeLayer()
newLayer.dataProvider().addAttributes(layer.fields())
Beim Erstellen eines Features wird der ursprüngliche Attributwert vererbt.
inFeat = QgsFeature()
feats = layer.getFeatures()
while feats.nextFeature( inFeat ):
attributes = inFeat.attributes()
geometry = QgsGeometry( inFeat.geometry() )
#Tatsächlich werden hier die Koordinaten konvertiert
feature = QgsFeature(fields)
feature.setAttributes(attributes)
feature.setGeometry(geometry)
newLayer.addFeature(feature)
Nachdem jeder Prozess abgeschlossen ist, werden wir ihn in das Plug-In einbetten.
###################################
#Klicken Sie auf die Schaltfläche Prozessstart
###################################
def buttonClicked(self):
self.layer = self.iface.activeLayer()
if not self.isScope():
return
self.wkbType = QgsWkbTypes.displayString(self.layer.wkbType())
#Generieren Sie ein Wörterbuch für die Koordinatenkonvertierungsparameter
self.loadPar()
#Generieren Sie eine Koordinatentransformationsklasse
self.setCrsTrans()
#Umwandlungsprozess
self.execTrans()
QMessageBox.information(self.dlg, 'tky2jgd', 'finished')
###################################
#Konvertierungsparameterdatei lesen
###################################
def loadPar(self):
self.par = {}
parfile = 'TKY2JGD.par'
with open(os.path.join(os.path.abspath(os.path.dirname(__file__)), parfile)) as f:
#Überspringen Sie zwei Zeilen in der Kopfzeile
skip = 2
for i in range(skip):
next(f)
#Zeile für Zeile lesen und in Liste speichern
while True:
line = f.readline()
if not line:
# EOF
break
#Der Wert ist Sekunden, also teilen Sie ihn hier
self.par[int(line[0:8])] = (float(line[8:18]) / 3600, float(line[18:28]) / 3600)
###################################
#Bestimmen Sie, ob es sich um eine Conversion-Zielebene handelt
#(Übrigens, behalten Sie die srid- und Längen- / Breitengrad-Flags vor und nach der Konvertierung bei.)
###################################
def isScope(self):
try:
if not isinstance(self.layer, QgsVectorLayer):
raise ValueError("activeLayer is not QgsVectorLayer")
self.srid = self.layer.crs().postgisSrid()
if self.srid == 4301:
self.isLonlat = True
self.toSrid = 4612
elif (self.srid > 30160 and self.srid < 30180):
self.isLonlat = False
self.toSrid = 2442 + self.srid - 30160
else:
#Nicht zutreffende SRID
raise ValueError("activeLayer is not Tokyo Datum")
wkbType = self.layer.wkbType()
#Ziellinienpolygon
if not QgsWkbTypes.geometryType(wkbType) in [
QgsWkbTypes.PointGeometry,
QgsWkbTypes.LineGeometry,
QgsWkbTypes.PolygonGeometry]:
#Nicht zutreffender GeometryType
raise ValueError("activeLayer is out of scope geometryType")
#Targeting von 2D-Ebenen
if QgsWkbTypes.hasZ(wkbType) or QgsWkbTypes.hasM(wkbType):
#Nicht zutreffend wkbType
raise ValueError("activeLayer is out of scope wkbType")
except ValueError as e:
#Unzutreffend
self.iface.messageBar().pushMessage("tky2jgd <b>{}</b>".format(e), Qgis.Warning)
return False
else:
#Ziel
return True
###################################
#Konvertierungsprozess koordinieren
###################################
def execTrans(self):
#Ebene nach der Konvertierung generieren
afterLayer = self.createAfterLayer()
#Beginnen Sie die Bearbeitung
afterLayer.startEditing()
fields = afterLayer.fields()
inFeat = QgsFeature()
feats = self.layer.getFeatures()
while feats.nextFeature( inFeat ):
attributes = inFeat.attributes()
beforeGeom = QgsGeometry( inFeat.geometry() )
if not self.isLonlat:
beforeGeom.transform(self.trans4301)
afterGeom = self.moveCorrection(beforeGeom)
if not self.isLonlat:
afterGeom.transform(self.transTo)
feature = QgsFeature(fields)
feature.setAttributes(attributes)
feature.setGeometry(afterGeom)
afterLayer.addFeature(feature)
#Ende der Bearbeitung
afterLayer.commitChanges()
QgsProject.instance().addMapLayer(afterLayer)
###################################
#Erstellen Sie eine konvertierte Speicherebene
###################################
def createAfterLayer(self):
layerUri = self.wkbType +"?crs=postgis:" + str(self.toSrid)
afterLayer = QgsVectorLayer(layerUri, "exchange", "memory")
afterLayer.dataProvider().addAttributes(self.layer.fields())
return afterLayer
###################################
#Verschieben des oberen Bereichs eines Features
###################################
def moveCorrection(self, geom):
for i, v in enumerate(geom.vertices()):
meshcode = self.Coordinate2MeshCode(v.y(), v.x())
correction = self.par[meshcode]
geom.moveVertex(v.x() + correction[1], v.y() + correction[0], i)
return geom
###################################
#Generieren Sie eine Koordinatentransformationsklasse
###################################
def setCrsTrans(self):
crs4301 = QgsCoordinateReferenceSystem(4301, QgsCoordinateReferenceSystem.EpsgCrsId)
if not self.isLonlat:
crsFrom = QgsCoordinateReferenceSystem(self.srid, QgsCoordinateReferenceSystem.EpsgCrsId)
self.trans4301 = QgsCoordinateTransform(crsFrom, crs4301, QgsProject.instance())
crsTo = QgsCoordinateReferenceSystem(self.toSrid, QgsCoordinateReferenceSystem.EpsgCrsId)
self.transTo = QgsCoordinateTransform(crs4301, crsTo, QgsProject.instance())
Ich habe nicht richtig mit dem Klassendesign angefangen, also war es irgendwie chaotisch. Dieser Bereich wird am Ende in Klassen unterteilt und organisiert, und wir werden dem Umzug zuerst Priorität einräumen. Es ist so langweilig, dass die isScope-Funktion mich sterben lässt.
Es ist mühsam, Beispieldaten nüchtern zu machen.
Lassen Sie uns überprüfen, ob die von uns erstellten Beispieldaten auch im rechten Winkel zur Ebene konvertiert werden können.
Die SRID der konvertierten Schicht ist ordnungsgemäß 2458. © OpenStreetMap contributors
Schicht | X | Y |
---|---|---|
Vor der Konvertierung | -21165 | -177520 |
Nach der Konvertierung | -21313 | -177066 |
Webversion TKY2JGD | -21315.4052 | -177083.9327 |
Der Fehler in Y-Richtung ist groß, aber wenn die Berechnung falsch ist, sollte dieser Fehler nicht ausreichen. Vielleicht ist er in Ordnung?
Versuchen wir es weiter in Tokio. Gleichzeitig wird der Geometrietyp überprüft.
Mehrpunktschichten können ebenfalls konvertiert werden, und die SRID dieser Schicht ist 2451. © OpenStreetMap contributors
Schicht | X | Y |
---|---|---|
Vor der Konvertierung | -6984 | -34730 |
Nach der Konvertierung | -7276 | -34371 |
Webversion TKY2JGD | -7277.1503 | -34374.4408 |
Ich habe kein schlechtes Gefühl, aber ich schließe die Augen und gehe weiter.
Überprüfen Sie nun, ob die Attribute vererbt wurden Fügen Sie der Speicherebene Zeichen-, Ganzzahl- und Gleitkommaspalten hinzu und fügen Sie dann Features hinzu. Geben wir einen Attributwert an. Wenn die Attribute der konvertierten Ebene angezeigt werden, werden sie ordnungsgemäß beibehalten.
Damit sind alle Funktionen implementiert, die Gegenstand dieser Zeit waren.
Klicken Sie hier für die bisherige Quelle
Versuchen Sie, die konvertierte Ebene in einem Shapefile zu speichern. Das angegebene CRS ist natürlich das der konvertierten Schicht. Wenn ich das gespeicherte Shapefile erneut in QGIS lade, verschiebt es sich. Ich muss in der Nähe der ursprünglichen Ebene fliegen, aber ich komme an den konvertierten Ort. Wenn ich die Koordinaten überprüfe, sind sie wirklich nicht ausgerichtet. Ein Wert, der dem Wert ähnlich ist, der erhalten wird, indem die alten Koordinaten in die neuen Koordinaten konvertiert und dann in die neuen Koordinaten verschoben werden.
Möglicherweise haben Sie den falschen Weg gefunden, um es Ihrem Projekt hinzuzufügen, oder Sie haben zuvor einen grundlegenden Fehler gemacht. Normalerweise denke ich, dass Sie nach der Behebung des Problems posten sollten, aber es ist in Ordnung, solche Versuche und Irrtümer zu haben. Deshalb gehe ich schlafen, daher kann ich es eine Weile nicht aktualisieren, aber das nächste Mal werde ich diesen Fehler untersuchen.
Nach dem Verschieben mit der Parameterdatei bei der Konvertierung von Breiten- und Längengrad war es ein Fehler, mit QgsCoordinateTransform weiter von den alten Koordinaten in die neuen Koordinaten zu konvertieren, sodass ich sie einschließlich "Teil 1" korrigierte. Infolgedessen wurde die Umrechnung von Längen- und Breitengraden normal. Es wurde festgestellt, dass der Bewegungsbetrag der Parameterdatei beim Konvertieren der Ebenenorthogonalität verdoppelt wurde. Die Ursache hierfür wurde noch nicht gefunden.
![Creative Commons License](https://i.creativecommons.org/l/by/4.0 /88x31.png) Dieser Artikel wird unter Creative Commons Attribution 4.0 International License bereitgestellt.
Recommended Posts