class SetPointMapTool(QgsMapToolEmitPoint): def __init__(self, canvas): self.canvas = canvas QgsMapToolEmitPoint.__init__(self, self.canvas) self.vertexMarker = QgsVertexMarker(self.canvas) self.vertexMarker.setColor(Qt.red) self.vertexMarker.setCursor(Qt.CrossCursor) self.reset() def reset(self): self.centerPoint = None self.vertexMarker.hide() #self.isEmittingPoint = False #self.rubberBand.reset(QGis.Polygon) def canvasPressEvent(self, e): self.centerPoint = self.toMapCoordinates(e.pos()) self.vertexMarker.setCenter(self.centerPoint) if not self.vertexMarker.isVisible(): self.vertexMarker.show() #self.endPoint = self.startPoint #self.isEmittingPoint = True #self.showRect(self.startPoint, self.endPoint) def canvasReleaseEvent(self, e): return #self.isEmittingPoint = False # r = self.rectangle() #if r is not None: # print "Rectangle:", r.xMinimum(), r.yMinimum(), r.xMaximum(), r.yMaximum() def canvasMoveEvent(self, e): return #if not self.isEmittingPoint: #return #self.endPoint = self.toMapCoordinates(e.pos()) #self.showRect(self.startPoint, self.endPoint) def rectangle(self): if self.startPoint is None or self.endPoint is None: return None elif self.startPoint.x() == self.endPoint.x() or self.startPoint.y( ) == self.endPoint.y(): return None return QgsRectangle(self.startPoint, self.endPoint) def deactivate(self): super(SetPointMapTool, self).deactivate() #self.emit(SIGNAL("deactivated()")) self.deactivated.emit()
class APISImageMapping(QDockWidget, FORM_CLASS): def __init__(self, iface, dbm, apisLayer, parent=None): """Constructor.""" super(APISImageMapping, self).__init__(parent) self.iface = iface self.dbm = dbm self.apisLayer = apisLayer self.setupUi(self) self.settings = QSettings(QSettings().value("APIS/config_ini"), QSettings.IniFormat) self.iface.addDockWidget(Qt.RightDockWidgetArea, self) self.hide() self.canvas = self.iface.mapCanvas() self.imageCenterPoint = None self.cpLayerId = None self.fpLayerId = None self.currentFilmNumber = None self.isOblique = True self.uiEditProjectTableObliqueBtn.clicked.connect( lambda: self.openSystemTableEditorDialog( "projekt", self.uiProjectObliqueCombo)) self.uiEditProjectTableVerticalBtn.clicked.connect( lambda: self.openSystemTableEditorDialog( "projekt", self.uiProjectVerticalCombo)) self.visibilityChanged.connect(self.onVisibilityChanged) self.setPointMapTool = QgsMapToolEmitPoint( self.canvas) # etPointMapTool(self.canvas) self.setPointMapTool.canvasClicked.connect(self.updatePoint) #self.setPointMapTool.canvasDoubleClicked.connect(self.handleDoubleClick) self.setPointMapTool.setButton(self.uiSetCenterPointBtn) self.uiSetCenterPointBtn.setCheckable(True) self.uiSetCenterPointBtn.toggled.connect(self.toggleSetCenterPoint) #self.uiSetCenterPointBtn.clicked.connect(self.activateSetCenterPoint) self.vertexMarker = QgsVertexMarker(self.canvas) self.vertexMarker2 = QgsVertexMarker(self.canvas) self.vertexMarker.setIconType(3) self.vertexMarker2.setIconType(1) self.vertexMarker.setColor(QColor(255, 153, 0)) self.vertexMarker2.setColor(QColor(255, 153, 0)) self.vertexMarker.setIconSize(12) self.vertexMarker2.setIconSize(20) self.vertexMarker.hide() self.vertexMarker2.hide() self.filmSelectionDlg = APISFilmNumberSelection() self.uiFilmSelectionBtn.clicked.connect(self.openFilmSelectionDialog) self.uiAutoImportBtn.clicked.connect(self.openAutoImportDialog) self.uiAddCenterPointBtn.clicked.connect(self.startAddingDetails) self.uiCancelCenterPointBtn.clicked.connect( self.onCancelAddCenterPoint) self.uiSaveCenterPointBtn.clicked.connect(self.onSaveAddCenterPoint) self.uiGenerateFootprintsBtn.clicked.connect(self.generateFootprints) self.uiAddProjectObliqueBtn.clicked.connect(self.addProjectOblique) self.uiAddProjectVerticalBtn.clicked.connect(self.addProjectVertical) self.uiRemoveProjectObliqueBtn.clicked.connect( self.removeProjectOblique) self.uiRemoveProjectVerticalBtn.clicked.connect( self.removeProjectVertical) self.resetCurrentFilmNumber() self.mappingMode = False def onVisibilityChanged(self, isVisible): if not isVisible: self.vertexMarker.hide() self.vertexMarker2.hide() if self.uiSetCenterPointBtn.isChecked(): self.uiSetCenterPointBtn.toggle() self.removeCenterPointLayer() self.removeFootPrintLayer() self.apisLayer.removeLayerGroupIfEmpty("Bildkartierung") else: if self.currentFilmNumber: self.reloadFpLayer() self.reloadCpLayer() if self.mappingMode: self.vertexMarker.show() self.vertexMarker2.show() def openFilmSelectionDialog(self): """Run method that performs all the real work""" self.filmSelectionDlg.show() self.filmSelectionDlg.uiFilmNumberEdit.setFocus() if self.filmSelectionDlg.exec_(): if not self.checkFilmNumber(self.filmSelectionDlg.filmNumber()): self.resetCurrentFilmNumber() #self.openFilmSelectionDialog() else: self.setCurrentFilmNumber(self.filmSelectionDlg.filmNumber()) def openSystemTableEditorDialog(self, table, editor): if self.dbm: self.systemTableEditorDlg = APISAdvancedInputDialog( self.dbm, table, True, modelColumnName="bezeichnung", excludeEntries=[ editor.itemText(i) for i in range(editor.count()) ], parent=self) if self.systemTableEditorDlg.tableExists: if self.systemTableEditorDlg.exec_(): # QMessageBox.information(self, "info", "{}".format(self.systemTableEditorDlg.getValueToBeAdded())) self.updateProjectListOfFilm( self.systemTableEditorDlg.getValueToBeAdded(), editor) else: QMessageBox.warning( self, "Tabelle nicht vorhanden", "Die Tabelle {0} ist in der APIS Datenbank nicht vorhanden" .format(table)) else: QMessageBox.warning( self, "Warning Database", "Die APIS Datenbank konnte nicht gefunden werden.") def openAutoImportDialog(self): self.reloadFpLayer() self.reloadCpLayer() autoImportDlg = APISDigitalImageAutoImport(self.iface, self.dbm, self.apisLayer, self.cpLayer, self.fpLayer, self.currentFilmNumber, parent=self) autoImportDlg.show() if autoImportDlg.exec_(): self.cpLayer.updateExtents() self.fpLayer.updateExtents() def setCurrentFilmNumber(self, filmNumber): self.currentFilmNumber = filmNumber self.uiCurrentFilmNumberEdit.setText(self.currentFilmNumber) # Get Information & Stats: schräg/senk, bildanzahl, ... filmStatus = self.getFilmInfo( ) # filmStatus true/false depending if problems wiht film infos if not filmStatus: self.resetCurrentFilmNumber() return self.getMappingStats() self.updateMappingDetails() # Enable Controls self.setCurrentLayout(True, True, True, False) if not self.imageCenterPoint: self.uiAddCenterPointBtn.setEnabled(False) self.mappingMode = False #if not self.uiSetCenterPointBtn.isChecked(): # self.uiSetCenterPointBtn.toggle() # Remove old Layer & Load New Layer self.removeCenterPointLayer() self.removeFootPrintLayer() self.loadFootPrintLayerForFilm() self.loadCenterPointLayerForFilm() def resetCurrentFilmNumber(self): self.uiCurrentFilmNumberEdit.clear() self.currentFilmNumber = None self.setCurrentLayout(True, False, False, False) #self.canvas.unsetMapTool(self.setPointMapTool) self.mappingMode = False if self.uiSetCenterPointBtn.isChecked(): self.uiSetCenterPointBtn.toggle() self.vertexMarker.hide() self.vertexMarker2.hide() # Reset & Remove Layer!!! self.removeCenterPointLayer() self.removeFootPrintLayer() def enableItemsInLayout(self, layout, enable): for i in range(layout.count()): if layout.itemAt(i).widget(): layout.itemAt(i).widget().setEnabled(enable) def visibleItemsInLayout(self, layout, visible): for i in range(layout.count()): if layout.itemAt(i).widget(): layout.itemAt(i).widget().setVisible(visible) def checkFilmNumber(self, filmNumber): if IsFilm(self.dbm.db, filmNumber): # Film exists return True else: # Film does not exist QMessageBox.warning( None, u"Film Nummer", u"Der Film mit der Nummer {0} existiert nicht!".format( filmNumber)) return False def getFilmInfo(self): filmFields = [ "filmnummer_hh_jjjj_mm", "filmnummer_nn", "filmnummer", "anzahl_bilder", "form1", "form2", "weise", "kammerkonstante", "datum_ersteintrag", "datum_aenderung", "projekt", "copyright" ] self.currentFilmInfoDict = {} query = QSqlQuery(self.dbm.db) qryStr = "SELECT {0} FROM film WHERE filmnummer = '{1}'".format( ", ".join(filmFields), self.currentFilmNumber) query.exec_(qryStr) query.first() if query.value(0) is not None: for key in filmFields: value = query.value(query.record().indexOf(key)) self.currentFilmInfoDict[key] = value if self.currentFilmInfoDict["weise"] == u"schräg": self.orientation = "schraeg" self.isOblique = True else: self.orientation = "senk" self.isOblique = False # QMessageBox.information(None, "kkInfo0", f'type: {type(self.currentFilmInfoDict["kammerkonstante"])}') if isinstance( self.currentFilmInfoDict["kammerkonstante"], str ) and not self.currentFilmInfoDict["kammerkonstante"]: QMessageBox.warning( None, u"Film Nummer", u"Der senkrecht Film mit der Nummer {0} hat keine Kammerkonstante (Wird für die Berechnung des Bildmaßstabs und in Folge des Footprints benötigt.) Geben Sie im Film Dialog die Kammerkonstante an, um korrekte Footprints zu erhalten." .format(self.currentFilmNumber)) return False else: if not self.currentFilmInfoDict["kammerkonstante"] > 0: QMessageBox.warning( None, u"Film Nummer", u"Der senkrecht Film mit der Nummer {0} hat eine Kammerkonstante (={1}), die für die Berechnung des Bildmaßstabs und in Folge des Footprints ungeeignet ist! Geben Sie im Film Dialog die Kammerkonstante an, um korrekte Footprints zu erhalten. Falls Bildmittelpunkte bereits gesetzt sind (mit einem Maßstab = 0) müssen auch diese neu kartiert werden!" .format( self.currentFilmNumber, self.currentFilmInfoDict["kammerkonstante"])) return False return True else: QMessageBox.warning( None, u"Film Nummer", u"Der Film mit der Nummer {0} existiert nicht!".format( self.currentFilmNumber)) return False def getMappingStats(self): self.imageStatsDict = {} query = QSqlQuery(self.dbm.db) qryStr = "SELECT COUNT(*) AS anzahl_kartiert, MAX(bildnummer_nn) AS letzte_bildnummer, MIN(bildnummer_nn) AS erste_bildnummer FROM luftbild_{0}_cp WHERE filmnummer = '{1}'".format( self.orientation, self.currentFilmNumber) query.exec_(qryStr) query.first() statFields = [ "anzahl_kartiert", "letzte_bildnummer", "erste_bildnummer" ] if query.value(0) is not None: for key in statFields: idx = query.record().indexOf(key) if query.isNull(idx): self.imageStatsDict[key] = 0 else: self.imageStatsDict[key] = query.value(idx) #QMessageBox.warning(None, u"Film Nummer", u"{0}, {1}, {2}".format(self.imageStatsDict["anzahl_kartiert"],self.imageStatsDict["letzte_bildnummer"],self.imageStatsDict["erste_bildnummer"])) else: self.imageStatsDict["anzahl_kartiert"] = 0 self.imageStatsDict["letzte_bildnummer"] = 0 self.imageStatsDict["erste_bildnummer"] = 0 QMessageBox.warning( None, u"Film Nummer", u"Für den Film mit der Nummer {0} sind noch keine Bilder kartiert!" .format(self.currentFilmNumber)) def updateMappingDetails(self): if self.isOblique: self.uiMappingDetailsTBox.setCurrentIndex(0) self.uiImageNumberFromSpn.setValue( self.imageStatsDict["letzte_bildnummer"] + 1) self.uiImageNumberToSpn.setValue( self.imageStatsDict["letzte_bildnummer"] + 1) # Projekte # DropDown Reset # von Film in DropDown hinzufügen self.uiProjectObliqueCombo.clear() if self.currentFilmInfoDict["projekt"]: self.uiProjectObliqueCombo.addItems( str.split(self.currentFilmInfoDict["projekt"], ";")) else: #deactivate buttons pass else: self.uiMappingDetailsTBox.setCurrentIndex(1) self.uiImageNumberSpn.setValue( self.imageStatsDict["letzte_bildnummer"] + 1) self.uiProjectVerticalCombo.clear() if self.currentFilmInfoDict["projekt"]: self.uiProjectVerticalCombo.addItems( str.split(self.currentFilmInfoDict["projekt"], ";")) else: #deactivate buttons pass def updateProjectListOfFilm(self, newValue, editor): # QMessageBox.information(self, "Info", "'{0};{1}'".format(self.currentFilmInfoDict["projekt"], newValue)) if self.currentFilmInfoDict["projekt"]: qryStr = "UPDATE film SET projekt = '{0}' WHERE filmnummer = '{1}'".format( "{0};{1}".format(self.currentFilmInfoDict["projekt"], newValue), self.currentFilmNumber) else: qryStr = "UPDATE film SET projekt = '{0}' WHERE filmnummer = '{1}'".format( newValue, self.currentFilmNumber) query = QSqlQuery(self.dbm.db) res = query.exec_(qryStr) if res: # update Film info and comboBox if self.currentFilmInfoDict["projekt"]: self.currentFilmInfoDict["projekt"] = "{0};{1}".format( self.currentFilmInfoDict["projekt"], newValue) else: self.currentFilmInfoDict["projekt"] = "{0}".format(newValue) editor.clear() if self.currentFilmInfoDict["projekt"]: editor.addItems( str.split(self.currentFilmInfoDict["projekt"], ";")) editor.setCurrentIndex(editor.count() - 1) self.dbm.dbRequiresUpdate = True else: QMessageBox.warning( self, "DB Fehler", "Der folgende Feheler ist aufgetreten: {}".format( query.lastError().text())) def toggleSetCenterPoint(self, isChecked): if isChecked: self.canvas.setMapTool(self.setPointMapTool) self.iface.messageBar().pushMessage( u"APIS Bild Kartierung", u"Positionieren Sie den Bildmittelpunkt mit der linken Maustaste und klicken Sie auf das Plus Symbol (oder verwenden Sie die reche Maustaste)", level=Qgis.Info) self.vertexMarker.show() self.vertexMarker2.show() else: self.canvas.unsetMapTool(self.setPointMapTool) self.iface.actionPan().trigger() if not self.mappingMode: self.vertexMarker.hide() self.vertexMarker2.hide() self.iface.messageBar().clearWidgets() def updatePoint(self, point, button): self.reloadCpLayer() self.imageCenterPoint = self.canvas.mapSettings( ).mapToLayerCoordinates(self.cpLayer, QgsPointXY(point)) #self.gl.setLocation(self.imageCenterPoint) self.vertexMarker.setCenter(point) self.vertexMarker2.setCenter(point) self.uiXCoordinateLbl.setText("{}".format(point.x())) self.uiYCoordinateLbl.setText("{}".format(point.y())) self.uiAddCenterPointBtn.setEnabled(True) if not self.vertexMarker.isVisible(): self.vertexMarker.show() self.vertexMarker2.show() if button == Qt.RightButton: self.startAddingDetails() def startAddingDetails(self): # Disable Layouts self.mappingMode = True if self.uiSetCenterPointBtn.isChecked(): self.uiSetCenterPointBtn.toggle() self.setCurrentLayout(False, False, False, True) self.uiMappingDetailsTBox.setItemEnabled(int(self.isOblique), False) def loadCenterPointLayerForFilm(self): self.cpLayer = self.apisLayer.requestSpatialiteTable( self.dbm.db.databaseName(), "luftbild_{0}_cp".format(self.orientation), displayName="Kartierung {0} Mittelpunkt".format( self.currentFilmNumber), groupName="Bildkartierung", subsetString='"filmnummer" = "{0}"'.format(self.currentFilmNumber), useLayerFromTree=False, addToCanvas=True, stylePath=self.apisLayer.getStylePath("image_mapping_cp")) self.cpLayerId = self.cpLayer.id() def loadFootPrintLayerForFilm(self): self.fpLayer = self.apisLayer.requestSpatialiteTable( self.dbm.db.databaseName(), "luftbild_{0}_fp".format(self.orientation), displayName="Kartierung {0} Footprint".format( self.currentFilmNumber), groupName="Bildkartierung", subsetString='"filmnummer" = "{0}"'.format(self.currentFilmNumber), useLayerFromTree=False, addToCanvas=True, stylePath=self.apisLayer.getStylePath("image_mapping_fp")) self.fpLayerId = self.fpLayer.id() def removeCenterPointLayer(self): if self.cpLayerId in QgsProject.instance().mapLayers(): QgsProject.instance().removeMapLayer(self.cpLayer.id()) def removeFootPrintLayer(self): if self.fpLayerId in QgsProject.instance().mapLayers(): QgsProject.instance().removeMapLayer(self.fpLayer.id()) def onCancelAddCenterPoint(self): self.setCurrentLayout(True, True, True, False) self.getMappingStats() self.updateMappingDetails() #self.canvas.setMapTool(self.setPointMapTool) self.mappingMode = False if not self.uiSetCenterPointBtn.isChecked(): self.uiSetCenterPointBtn.toggle() def onSaveAddCenterPoint(self): #QMessageBox.warning(None, u"Film Nummer", u"{0},{1},{2}".format(self.imageCenterPoint.x(), self.imageCenterPoint.y(), type(self.imageCenterPoint))) self.reloadCpLayer() #Prepare Image Numbers if self.isOblique: fromImageNumber = self.uiImageNumberFromSpn.value() toImageNumber = self.uiImageNumberToSpn.value() if fromImageNumber > toImageNumber: QMessageBox.warning( None, u"Bild Nummern", u"Die erste Bildnummer darf nicht größer als die zweite sein." ) return else: imageNumbers = range(fromImageNumber, toImageNumber + 1) else: imageNumbers = [self.uiImageNumberSpn.value()] # filmImageNumbers = [] # for imageNumber in imageNumbers: # filmImageNumbers.append('{0}.{1:03d}'.format(self.currentFilmNumber, imageNumber)) # QMessageBox.warning(None, u"Bild Nummern", ",".join(imageNumbers)) # for filmImageNumber in self.cpLayer.getValues("BILD"): # QMessageBox.warning(None, u"Bild Nummern", "{0}".format(filmImageNumber)) # Check if Image Number in Table for imageNumber in imageNumbers: # QMessageBox.warning(None, u"Bild Nummern", u"{0}".format(QgsVectorLayerUtils.getValues(self.cpLayer, "bildnummer_nn"))) if imageNumber in QgsVectorLayerUtils.getValues( self.cpLayer, "bildnummer_nn")[0]: QMessageBox.warning( None, u"Bild Nummern", u"Ein Bild mit der Nummer {0} wurde bereits kartiert". format(imageNumber)) return caps = self.cpLayer.dataProvider().capabilities() if caps & QgsVectorDataProvider.AddFeatures: features = [] feat = QgsFeature(self.cpLayer.fields()) feat.setGeometry(QgsGeometry.fromPointXY(self.imageCenterPoint)) # From Film Table # filmFields = ["form1", "form2", "weise", "kammerkonstante"] feat.setAttribute( 'filmnummer_hh_jjjj_mm', self.currentFilmInfoDict["filmnummer_hh_jjjj_mm"]) feat.setAttribute('filmnummer_nn', self.currentFilmInfoDict["filmnummer_nn"]) feat.setAttribute('filmnummer', self.currentFilmNumber) #Date TODAY now = QDate.currentDate() feat.setAttribute('datum_ersteintrag', now.toString("yyyy-MM-dd")) feat.setAttribute('datum_aenderung', now.toString("yyyy-MM-dd")) # Iterate over Project Selection List und String mit ; trennung generieren feat.setAttribute('copyright', self.currentFilmInfoDict["copyright"]) # By Default Fix Value feat.setAttribute('etikett', 0) # Get Projects from Projekte Liste items = [] # From Input (Radius, Höhe, Schlüsslewort, Beschreibung) if self.isOblique: feat.setAttribute('radius', float(self.uiImageDiameterSpn.value() / 2)) feat.setAttribute('beschreibung', self.uiImageDescriptionEdit.text()) h = self.uiFlightHeightObliqueSpn.value() for j in range(self.uiProjectObliqueList.count()): items.append(self.uiProjectObliqueList.item(j)) else: h = self.uiFlightHeightVerticalSpn.value() feat.setAttribute('fokus', self.currentFilmInfoDict["kammerkonstante"]) if not self.currentFilmInfoDict[ "kammerkonstante"] or not self.currentFilmInfoDict[ "kammerkonstante"] > 0: feat.setAttribute('massstab', 0) else: feat.setAttribute( 'massstab', h / self.currentFilmInfoDict["kammerkonstante"] * 1000) for j in range(self.uiProjectVerticalList.count()): items.append(self.uiProjectVerticalList.item(j)) feat.setAttribute('projekt', ";".join([i.text() for i in items])) feat.setAttribute('hoehe', h) # Calculated/Derived feat.setAttribute('longitude', self.imageCenterPoint.x()) feat.setAttribute('latitude', self.imageCenterPoint.y()) countryCode = self.getCountryCode() feat.setAttribute('land', countryCode) if countryCode == 'AUT': # get meridian and epsg Code meridian, epsgGK = GetMeridianAndEpsgGK( self.imageCenterPoint.x()) # get KG Coordinates gk = TransformGeometry( QgsGeometry().fromPointXY(self.imageCenterPoint), self.cpLayer.crs(), QgsCoordinateReferenceSystem(f"EPSG:{epsgGK}")) gkx = gk.asPoint().y() # Hochwert gky = gk.asPoint().x() # Rechtswert else: meridian = None gkx = None gky = None feat.setAttribute('meridian', meridian) feat.setAttribute('gkx', gkx) # Hochwert feat.setAttribute('gky', gky) # Rechtswert for imageNumber in imageNumbers: f = QgsFeature(feat) f.setAttribute('bildnummer_nn', imageNumber) bn = '{0}.{1:03d}'.format(self.currentFilmNumber, imageNumber) f.setAttribute('bildnummer', bn) if self.isOblique: image = os.path.normpath( self.settings.value("APIS/image_dir") + '\\' + self.currentFilmNumber + '\\' + bn.replace('.', '_') + '.jpg') exif = GetExifForImage(image, altitude=True, longitude=True, latitude=True, exposure_time=True, focal_length=True, fnumber=True) if "altitude" in exif and exif["altitude"]: f.setAttribute('hoehe', exif["altitude"]) f.setAttribute( 'gps_longitude', exif["longitude"] if "longitude" in exif else None) f.setAttribute( 'gps_latitude', exif["latitude"] if "latitude" in exif else None) if "longitude" in exif and "latitude" in exif and exif[ "longitude"] and exif["latitude"]: capturePoint = QgsPointXY(exif["longitude"], exif["latitude"]) kappa = capturePoint.azimuth(self.imageCenterPoint) else: kappa = None f.setAttribute('kappa', kappa) f.setAttribute( 'belichtungszeit', exif["exposure_time"] if "exposure_time" in exif else None) f.setAttribute('fokus', exif["focal_length"] if "focal_length" in exif else None) # FocalLength if "focal_length" in exif and "fnumber" in exif and exif[ "focal_length"] and exif["fnumber"]: blende = exif["focal_length"] / exif[ "fnumber"] # effecitve aperture (diameter of entrance pupil) = focalLength / fNumber else: blende = None f.setAttribute('blende', blende) features.append(f) (res, outFeats) = self.cpLayer.dataProvider().addFeatures(features) self.cpLayer.updateExtents() if res and self.isOblique: self.generateFootprintsForFilmOblique() #QMessageBox.warning(None, u"Film Nummer", u"{0},{1}".format(res, outFeats)) else: QMessageBox.warning(None, u"Layer Capabilities!") if self.canvas.isCachingEnabled(): self.cpLayer.triggerRepaint() else: self.canvas.refresh() self.onCancelAddCenterPoint() def getCountryCode(self): query = QSqlQuery(self.dbm.db) #qryStr = "SELECT code FROM osm_boundaries WHERE within(MakePoint({0}, {1}, 4312), geometry)".format(self.imageCenterPoint.x(), self.imageCenterPoint.y()) qryStr = "SELECT code FROM osm_boundaries WHERE intersects(Transform(MakePoint({0}, {1}, 4312), 4326), geometry) AND ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'osm_boundaries' AND search_frame = Transform(MakePoint({0}, {1}, 4312), 4326))".format( self.imageCenterPoint.x(), self.imageCenterPoint.y()) query.exec_(qryStr) query.first() if query.value(0) is None: return 'INT' else: return query.value(0) def reloadCpLayer(self): if self.cpLayerId not in QgsProject.instance().mapLayers(): self.loadCenterPointLayerForFilm() def reloadFpLayer(self): if self.fpLayerId not in QgsProject.instance().mapLayers(): self.loadFootPrintLayerForFilm() def generateFootprints(self): if self.isOblique: self.generateFootprintsForFilmOblique() else: self.generateFootprintsForFilmVertical() def generateFootprintsForFilmVertical(self): self.reloadFpLayer() self.reloadCpLayer() # Error wenn nur ein punkt vorhanden if self.cpLayer.featureCount() > 1: caps = self.fpLayer.dataProvider().capabilities() if caps & QgsVectorDataProvider.AddFeatures: #Get FORM1 from FilmInfoDict f1 = self.currentFilmInfoDict["form1"] # Image height f2 = self.currentFilmInfoDict["form2"] # Image width iterFeatures = self.cpLayer.getFeatures() iterNext = self.cpLayer.getFeatures() existingFootpints = QgsVectorLayerUtils.getValues( self.fpLayer, "bildnummer")[0] ft = QgsFeature() ftNext = QgsFeature() iterNext.nextFeature(ftNext) fpFeats = [] kappasToUpdate = {} # iterate over points from CP Layer > LON, LAT i = 0 while iterFeatures.nextFeature(ft): i += 1 iterNext.nextFeature(ftNext) p = QgsPointXY(ft.geometry().asPoint()) if ft['bildnummer'] in existingFootpints: pPrevGeom = QgsGeometry(ft.geometry()) #QMessageBox.warning(None, u"Bild Nummern", u"Footprint für das Bild mit der Nummer {0} wurde bereits erstellt.".format(ft['BILD'])) continue if i == 1: pPrevGeom = QgsGeometry(ftNext.geometry()) #if iterNext.isClosed(): # #use pPrev as pNext # pNext = QgsPoint(pPrev) #else: # pNext = QgsPoint(ftNext.geometry().asPoint()) #kappa = p.azimuth(pPrev) #kappa = p.azimuth(pNext) # d = math.sqrt(2*((f1/2 * ft['MASS']/1000)**2)) d1 = f1 / 2 * ft['massstab'] / 1000 d2 = f2 / 2 * ft['massstab'] / 1000 #QMessageBox.warning(None, u"Bild Nummern", "{0}".format(d)) calcCrs = QgsCoordinateReferenceSystem() calcCrs.createFromProj4(self.Proj4Utm(p)) ctF = QgsCoordinateTransform(self.cpLayer.crs(), calcCrs, QgsProject.instance()) cpMetric = QgsGeometry(ft.geometry()) cpMetric.transform(ctF) pPrevGeom.transform(ctF) pMetric = QgsPointXY(cpMetric.asPoint()) pPrevMetric = QgsPointXY(pPrevGeom.asPoint()) kappaMetric = pMetric.azimuth(pPrevMetric) pPrevGeom = QgsGeometry(ft.geometry()) left = pMetric.x() - d2 bottom = pMetric.y() - d1 right = pMetric.x() + d2 top = pMetric.y() + d1 #R = 6371 #D = (d/1000) #cpLat = math.radians(p.y()) #cpLon = math.radians(p.x()) #urLat = math.asin( math.sin(cpLat)*math.cos(D/R) + math.cos(cpLat)*math.sin(D/R)*math.cos(urBrng) ) #urLon = cpLon + math.atan2(math.sin(urBrng)*math.sin(D/R)*math.cos(cpLat), math.cos(D/R)-math.sin(cpLat)*math.sin(urLat)) #top = math.asin( math.sin(cpLat)*math.cos(D/R) + math.cos(cpLat)*math.sin(D/R) ) #bottom = math.asin( math.sin(cpLat)*math.cos(D/R) + math.cos(cpLat)*math.sin(D/R)*-1 ) #lat = math.asin( math.sin(cpLat)*math.cos(D/R) ) #right = cpLon + math.atan2(math.sin(D/R)*math.cos(cpLat), math.cos(D/R)-math.sin(cpLat)*math.sin(lat)) #left = cpLon + math.atan2(-1*math.sin(D/R)*math.cos(cpLat), math.cos(D/R)-math.sin(cpLat)*math.sin(lat)) #QMessageBox.warning(None, u"Bild Nummern", "{0}, {1}, {2}, {3}".format(math.degrees(top), math.degrees(bottom), math.degrees(left), math.degrees(right))) #rect = QgsRectangle(math.degrees(left), math.degrees(bottom), math.degrees(right), math.degrees(top)) #l = math.degrees(left) #b = math.degrees(bottom) #r = math.degrees(right) #t = math.degrees(top) p1 = QgsGeometry.fromPointXY(QgsPointXY(left, bottom)) p2 = QgsGeometry.fromPointXY(QgsPointXY(right, bottom)) p3 = QgsGeometry.fromPointXY(QgsPointXY(right, top)) p4 = QgsGeometry.fromPointXY(QgsPointXY(left, top)) #p1.rotate(kappa+90, p) #p2.rotate(kappa+90, p) #p3.rotate(kappa+90, p) #p4.rotate(kappa+90, p) pol = [[ p1.asPoint(), p2.asPoint(), p3.asPoint(), p4.asPoint() ]] geom = QgsGeometry.fromPolygonXY(pol) geom.rotate(kappaMetric, pMetric) #Transform to DestinationCRS ctB = QgsCoordinateTransform(calcCrs, self.fpLayer.crs(), QgsProject.instance()) geom.transform(ctB) feat = QgsFeature(self.fpLayer.fields()) feat.setGeometry(geom) feat.setAttribute('filmnummer', self.currentFilmNumber) feat.setAttribute('bildnummer', ft['bildnummer']) da = QgsDistanceArea() da.setEllipsoid(self.fpLayer.crs().ellipsoidAcronym()) feat.setAttribute('shape_length', da.measurePerimeter(geom)) feat.setAttribute('shape_area', da.measureArea(geom)) fpFeats.append(feat) # update Kappa in cpLayer kappasToUpdate[ft.id()] = { ft.fieldNameIndex('kappa'): kappaMetric } iterFeatures.close() iterNext.close() resCAVs = self.cpLayer.dataProvider().changeAttributeValues( kappasToUpdate) QgsMessageLog.logMessage( f"Kappa Update for {kappasToUpdate}, Success: {resCAVs}", tag="APIS", level=Qgis.Success if resCAVs else Qgis.Critical) (res, outFeats) = self.fpLayer.dataProvider().addFeatures(fpFeats) self.fpLayer.updateExtents() if self.canvas.isCachingEnabled(): self.fpLayer.triggerRepaint() else: self.canvas.refresh() else: #Caps QMessageBox.warning(None, "Layer Capabilities!", "Layer Capabilities!") else: #small feature count QMessageBox.warning( None, "Footprints", "Zum Berechnen der senkrecht Footprint müssen mindestens zwei Bilder kartiert werden!" ) def generateFootprintsForFilmOblique(self): self.reloadFpLayer() self.reloadCpLayer() caps = self.fpLayer.dataProvider().capabilities() if caps & QgsVectorDataProvider.AddFeatures: if self.cpLayer.dataProvider().featureCount() > 0: iter = self.cpLayer.getFeatures() existingFootpints = QgsVectorLayerUtils.getValues( self.fpLayer, "bildnummer")[0] cpFt = QgsFeature() fpFts = [] #iterate over points from CP Layer > LON, LAT while iter.nextFeature(cpFt): if cpFt['bildnummer'] in existingFootpints: #QMessageBox.warning(None, u"Bild Nummern", u"Footprint für das Bild mit der Nummer {0} wurde bereits erstellt.".format(ft['BILD'])) continue cp = cpFt.geometry() cpMetric = QgsGeometry(cp) destCrs = QgsCoordinateReferenceSystem() destCrs.createFromProj4(self.Proj4Utm(cp.asPoint())) coordTransformF = QgsCoordinateTransform( self.cpLayer.crs(), destCrs, QgsProject.instance()) coordTransformB = QgsCoordinateTransform( destCrs, self.cpLayer.crs(), QgsProject.instance()) cpMetric.transform(coordTransformF) if cpFt['radius'] == '': r = 175 else: r = float(cpFt['radius']) fpMetric = QgsGeometry(cpMetric.buffer(r, 18)) fp = QgsGeometry(fpMetric) fp.transform(coordTransformB) fpFt = QgsFeature(self.fpLayer.fields()) fpFt.setGeometry(fp) fpFt.setAttribute("bildnummer", cpFt["bildnummer"]) fpFt.setAttribute("filmnummer", cpFt["filmnummer"]) da = QgsDistanceArea() da.setEllipsoid(self.fpLayer.crs().ellipsoidAcronym()) fpFt.setAttribute('shape_length', da.measurePerimeter(fp)) fpFt.setAttribute('shape_area', da.measureArea(fp)) fpFts.append(fpFt) (res, outFeats) = self.fpLayer.dataProvider().addFeatures(fpFts) self.fpLayer.updateExtents() if self.canvas.isCachingEnabled(): self.fpLayer.triggerRepaint() else: self.canvas.refresh() else: QMessageBox.warning( None, "Keine Bildmittelpunkte", "Keine Bildmittelpunkte für den Film {0} vorhanden.". format(self.currentFilmNumber)) else: QMessageBox.warning( None, "Layer Capabilities", "AddFeature is not enabled ({0})".format( self.fpLayer.dataProvider().capabilitiesString())) def Proj4Utm(self, p): x = p.x() y = p.y() z = math.floor((x + 180) / 6) + 1 if y >= 56.0 and y < 64.0 and x >= 3.0 and x < 12.0: z = 32 #Special zones for Svalbard if y >= 72.0 and y < 84.0: if y >= 0.0 and y < 9.0: z = 31 elif y >= 9.0 and y < 21.0: z = 33 elif y >= 21.0 and y < 33.0: z = 35 elif y >= 33.0 and y < 42.0: z = 37 return "+proj=utm +zone={0} +datum=WGS84 +units=m +no_defs".format( int(z)) def setCurrentLayout(self, film=True, mapping=False, autoimport=False, details=False): self.enableItemsInLayout(self.uiFilmSelectionHorizontalLayout, film) self.enableItemsInLayout(self.uiMappingGridLayout, mapping) self.enableItemsInLayout(self.uiFootprintsVerticalLayout, mapping) self.enableItemsInLayout(self.uiAutoImportHorizontalLayout, autoimport) self.visibleItemsInLayout(self.uiMappingDetailsGridLayout, details) def addProjectOblique(self): self.addProject(self.uiProjectObliqueList, self.uiProjectObliqueCombo.currentText()) def addProjectVertical(self): self.addProject(self.uiProjectVerticalList, self.uiProjectVerticalCombo.currentText()) def removeProjectOblique(self): self.removeProject(self.uiProjectObliqueList) def removeProjectVertical(self): self.removeProject(self.uiProjectVerticalList) def addProject(self, editor, value): notInList = True for row in range(editor.count()): if value == editor.item(row).data(0): notInList = False break if notInList: editor.addItem(value) editor.sortItems() def removeProject(self, editor): editor.takeItem(editor.currentRow())