if __name__ == '__console__': print("-----------------------------------------------\n\n") # PostGIS SRID 4326 is allocated for WGS84 # If not specified otherwise in second parameter, PostGIS SRID is used by default. crs = QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.PostgisCrsId) print("Valid: ", crs.isValid()) print("QGIS CRS ID:", crs.srsid()) print("EPSG ID:", crs.authid()) print("Description:", crs.description()) print("Projection Acronym:", crs.projectionAcronym()) print("Ellipsoid Acronym:", crs.ellipsoidAcronym()) print("Proj4 String:", crs.toProj4()) # check whether it's geographic or projected coordinate system print("Is geographic:", crs.geographicFlag()) # check type of map units in this CRS (values defined in QGis::units enum) print("Map units:", crs.mapUnits()) print("-----------------------------------------------\n\n") wkt = '''GEOGCS["WGS84", DATUM["WGS84", SPHEROID["WGS84", 6378137.0, 298.257223563]], PRIMEM["Greenwich", 0.0], UNIT["degree", 0.017453292519943295], AXIS["Longitude", EAST], AXIS["Latitude", NORTH]]''' crs = QgsCoordinateReferenceSystem(wkt) print("Valid: ", crs.isValid()) print("QGIS CRS ID:", crs.srsid()) print("EPSG ID:", crs.authid()) print("Description:", crs.description()) print("Projection Acronym:", crs.projectionAcronym()) print("Ellipsoid Acronym:", crs.ellipsoidAcronym())
class ResampleImageToBlockDialog(QtGui.QDialog, FORM_CLASS): """Extract statistics from a list of rasters at set locations.""" toolKey = 'ResampleImageBandDialog' def __init__(self, iface, parent=None): super(ResampleImageToBlockDialog, self).__init__(parent) # Set up the user interface from Designer. self.setupUi(self) self.iface = iface self.DISP_TEMP_LAYERS = read_setting(PLUGIN_NAME + '/DISP_TEMP_LAYERS', bool) self.DEBUG = config.get_debug_mode() # Catch and redirect python errors directed at the log messages python error tab. QgsMessageLog.instance().messageReceived.connect(errorCatcher) if not os.path.exists(TEMPDIR): os.mkdir(TEMPDIR) # Setup for validation messagebar on gui----------------------------- self.messageBar = QgsMessageBar( self) # leave this message bar for bailouts self.validationLayout = QtGui.QFormLayout(self) # new layout to gui if isinstance(self.layout(), (QtGui.QFormLayout, QtGui.QGridLayout)): # create a validation layout so multiple messages can be added and cleaned up. self.layout().insertRow(0, self.validationLayout) self.layout().insertRow(0, self.messageBar) else: self.layout().insertWidget( 0, self.messageBar) # for use with Vertical/horizontal layout box self.outQgsCRS = None self.exclude_map_layers() self.updateRaster() self.updateUseSelected() self.autoSetCoordinateSystem() # GUI Runtime Customisation ----------------------------------------------- self.setWindowIcon( QtGui.QIcon(':/plugins/pat/icons/icon_resampleToBlock.svg')) self.chkAddToDisplay.setChecked(False) self.add_blank_field_to_cbo() # self.chkAddToDisplay.hide() def cleanMessageBars(self, AllBars=True): """Clean Messages from the validation layout. Args: AllBars (bool): Remove All bars including those which haven't timed-out. Defaults to True """ layout = self.validationLayout for i in reversed(range(layout.count())): # when it timed out the row becomes empty.... if layout.itemAt(i).isEmpty(): # .removeItem doesn't always work. so takeAt(pop) it instead item = layout.takeAt(i) elif AllBars: # ie remove all item = layout.takeAt(i) # also have to remove any widgets associated with it. if item.widget() is not None: item.widget().deleteLater() def send_to_messagebar(self, message, title='', level=QgsMessageBar.INFO, duration=5, exc_info=None, core_QGIS=False, addToLog=False, showLogPanel=False): """ Add a message to the forms message bar. Args: message (str): Message to display title (str): Title of message. Will appear in bold. Defaults to '' level (QgsMessageBarLevel): The level of message to log. Defaults to QgsMessageBar.INFO duration (int): Number of seconds to display message for. 0 is no timeout. Defaults to 5 core_QGIS (bool): Add to QGIS interface rather than the dialog addToLog (bool): Also add message to Log. Defaults to False showLogPanel (bool): Display the log panel exc_info () : Information to be used as a traceback if required """ if core_QGIS: newMessageBar = self.iface.messageBar() else: newMessageBar = QgsMessageBar(self) widget = newMessageBar.createMessage(title, message) if showLogPanel: button = QPushButton(widget) button.setText('View') button.setContentsMargins(0, 0, 0, 0) button.setFixedWidth(35) button.pressed.connect(openLogPanel) widget.layout().addWidget(button) newMessageBar.pushWidget(widget, level, duration=duration) if not core_QGIS: rowCount = self.validationLayout.count() self.validationLayout.insertRow(rowCount + 1, newMessageBar) if addToLog: if level == 1: # 'WARNING': LOGGER.warning(message) elif level == 2: # 'CRITICAL': # Add a traceback to log only for bailouts only if exc_info is not None: exc_type, exc_value, exc_traceback = sys.exc_info() mess = str(traceback.format_exc()) message = message + '\n' + mess LOGGER.critical(message) else: # INFO = 0 LOGGER.info(message) def exclude_map_layers(self): """ Run through all loaded layers to find ones which should be excluded. In this case exclude services.""" exVlayer_list = [] exRlayer_list = [] for layer in self.iface.legendInterface().layers(): if layer.type() == QgsMapLayer.RasterLayer: if layer.providerType() != 'gdal': exRlayer_list.append(layer) elif layer.type() == QgsMapLayer.VectorLayer: if layer.providerType() != 'ogr': exVlayer_list.append(layer) self.mcboRasterLayer.setExceptedLayerList(exRlayer_list) if len(exRlayer_list) > 0: pass if len(exVlayer_list) > 0: self.mcboPolygonLayer.setExceptedLayerList(exVlayer_list) def updateRaster(self): if self.mcboRasterLayer.currentLayer() is None: return layer = self.mcboRasterLayer.currentLayer() provider = layer.dataProvider() if provider.srcHasNoDataValue(1): self.spnNoDataVal.setValue(provider.srcNoDataValue(1)) elif len(provider.userNoDataValues(1)) > 0: self.spnNoDataVal.setValue(provider.userNoDataValues(1)[0].min()) else: self.spnNoDataVal.setValue(0) # add a band list to the drop down box bandCount = self.mcboRasterLayer.currentLayer().bandCount() band_list = ['Band {: >2}'.format(i) for i in range(1, bandCount + 1)] self.cboBand.setMaxCount(bandCount + 1) self.cboBand.clear() self.cboBand.addItems([u''] + sorted(band_list)) def updateUseSelected(self): """Update use selected checkbox if active layer has a feature selection""" self.chkUseSelected.setChecked(False) if self.mcboPolygonLayer.count() == 0: return polygon_lyr = self.mcboPolygonLayer.currentLayer() self.mFieldComboBox.setLayer(polygon_lyr) if len(polygon_lyr.selectedFeatures()) > 0: self.chkUseSelected.setText( 'Use the {} selected feature(s) ?'.format( len(polygon_lyr.selectedFeatures()))) self.chkUseSelected.setEnabled(True) else: self.chkUseSelected.setText('No features selected') self.chkUseSelected.setEnabled(False) def autoSetCoordinateSystem(self): if self.mcboRasterLayer.count() == 0: return self.cleanMessageBars() raster_lyr = self.mcboRasterLayer.currentLayer() raster_utm_crs = crs.getProjectedCRSForXY( raster_lyr.extent().xMinimum(), raster_lyr.extent().yMinimum(), int(raster_lyr.crs().authid().replace('EPSG:', ''))) self.outQgsCRS = None if raster_utm_crs is not None: raster_crs = QgsCoordinateReferenceSystem('EPSG:{}'.format( raster_utm_crs.epsg_number)) self.outQgsCRS = raster_crs if self.outQgsCRS is not None: self.lblOutCRS.setText('{} - {}'.format( self.outQgsCRS.description(), self.outQgsCRS.authid())) self.lblOutCRSTitle.setStyleSheet('color:black') self.lblOutCRS.setStyleSheet('color:black') else: self.lblOutCRSTitle.setStyleSheet('color:red') self.lblOutCRS.setStyleSheet('color:red') self.lblOutCRS.setText('Unspecified') self.send_to_messagebar( 'Auto detect coordinate system Failed. Check coordinate system of input raster layer', level=QgsMessageBar.CRITICAL, duration=5) return def add_blank_field_to_cbo(self, set=True): """ Add a blank string to the field combo box. Fixed in qgis 3""" if self.mFieldComboBox.findText('', QtCore.Qt.MatchFixedString) == -1: self.mFieldComboBox.addItem(u'') if set == True: self.mFieldComboBox.setField(u'') def on_mcboRasterLayer_layerChanged(self): self.updateRaster() self.autoSetCoordinateSystem() def on_mcboPolygonLayer_layerChanged(self): self.updateUseSelected() self.autoSetCoordinateSystem() # ToDo: QGIS 3 implement QgsMapLayerComboBox.allowEmptyLayer() instead of chkUsePoly checkbox self.chkUsePoly.setChecked(True) self.add_blank_field_to_cbo() @QtCore.pyqtSlot(int) def on_chkUsePoly_stateChanged(self, state): self.add_blank_field_to_cbo() self.mFieldComboBox.setEnabled(state) self.lblGroupByField.setEnabled(state) # def on_mFieldComboBox_fieldChanged(self, field): # # Problem : after selecting a field, the blank is removed from the pick list. # # Solution: Add it again.... but this doesn't work. # if self.mFieldComboBox.findText('', QtCore.Qt.MatchFixedString) == -1: # # work around for not having a physical blank in the list. Fixed in qgis 3 # self.mFieldComboBox.addItem(u'') def on_chkUseSelected_stateChanged(self, state): if self.chkUseSelected.isChecked(): self.chkUsePoly.setChecked(True) @QtCore.pyqtSlot(name='on_cmdOutCRS_clicked') def on_cmdOutCRS_clicked(self): dlg = QgsGenericProjectionSelector(self) dlg.setMessage(self.tr('Select coordinate system')) if dlg.exec_(): if dlg.selectedAuthId() != '': self.outQgsCRS = QgsCoordinateReferenceSystem( dlg.selectedAuthId()) if self.outQgsCRS.geographicFlag(): self.outQgsCRS = None self.send_to_messagebar(unicode( self. tr("Geographic coordinate systems are not allowed. Resetting to default.." )), level=QgsMessageBar.WARNING, duration=5) else: self.outQgsCRS = None if self.outQgsCRS is None: self.autoSetCoordinateSystem() self.lblOutCRSTitle.setStyleSheet('color:black') self.lblOutCRS.setStyleSheet('color:black') self.lblOutCRS.setText( self.tr('{} - {}'.format(self.outQgsCRS.description(), self.outQgsCRS.authid()))) @QtCore.pyqtSlot(name='on_cmdOutputFolder_clicked') def on_cmdOutputFolder_clicked(self): self.messageBar.clearWidgets() if self.lneOutputFolder.text() is None: outFolder = '' else: outFolder = self.lneOutputFolder.text() if outFolder == '': outFolder = read_setting(PLUGIN_NAME + "/" + self.toolKey + "/LastOutFolder") if outFolder is None or not os.path.exists(outFolder): outFolder = read_setting(PLUGIN_NAME + '/BASE_OUT_FOLDER') s = QtGui.QFileDialog.getExistingDirectory( self, self. tr("Save output files to a folder. A sub-folder will be created from the image name" ), outFolder, QtGui.QFileDialog.ShowDirsOnly) self.cleanMessageBars(self) if s == '' or s is None: return s = os.path.normpath(s) self.lblOutputFolder.setStyleSheet('color:black') self.lneOutputFolder.setStyleSheet('color:black') self.lneOutputFolder.setText(s) write_setting(PLUGIN_NAME + "/" + self.toolKey + "/LastOutFolder", s) def validate(self): """Check to see that all required gui elements have been entered and are valid.""" self.messageBar.clearWidgets() self.cleanMessageBars(AllBars=True) try: errorList = [] if self.mcboRasterLayer.currentLayer() is None: self.lblRasterLayer.setStyleSheet('color:red') errorList.append(self.tr("Input image layer required.")) else: self.lblRasterLayer.setStyleSheet('color:black') if self.cboBand.currentText() == '': self.lblBand.setStyleSheet('color:red') errorList.append(self.tr("Input band selection required.")) else: self.lblBand.setStyleSheet('color:black') if self.dsbPixelSize.value() <= 0: self.lblPixelSize.setStyleSheet('color:red') errorList.append(self.tr("Pixel size must be greater than 0.")) else: self.lblPixelSize.setStyleSheet('color:black') if self.outQgsCRS is None: self.lblOutCRSTitle.setStyleSheet('color:red') self.lblOutCRS.setStyleSheet('color:red') errorList.append( self.tr("Select output projected coordinate system")) else: if self.outQgsCRS.geographicFlag(): self.lblOutCRSTitle.setStyleSheet('color:red') self.lblOutCRS.setStyleSheet('color:red') errorList.append( self. tr("Output projected coordinate system (not geographic) required" )) else: self.lblOutCRSTitle.setStyleSheet('color:black') self.lblOutCRS.setStyleSheet('color:black') if self.lneOutputFolder.text() == '': self.lblOutputFolder.setStyleSheet('color:red') errorList.append(self.tr("Select output data folder")) elif not os.path.exists(self.lneOutputFolder.text()): self.lneOutputFolder.setStyleSheet('color:red') self.lblOutputFolder.setStyleSheet('color:red') errorList.append(self.tr("Output data folder does not exist")) else: self.lblOutputFolder.setStyleSheet('color:black') self.lneOutputFolder.setStyleSheet('color:black') if len(errorList) > 0: raise ValueError(errorList) except ValueError as e: self.cleanMessageBars(True) if len(errorList) > 0: for i, ea in enumerate(errorList): self.send_to_messagebar(unicode(ea), level=QgsMessageBar.WARNING, duration=(i + 1) * 5) return False return True def accept(self, *args, **kwargs): try: if not self.validate(): return False # disable form via a frame, this will still allow interaction with the message bar self.fraMain.setDisabled(True) # clean gui and Qgis messagebars self.cleanMessageBars(True) # Change cursor to Wait cursor QtGui.qApp.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) self.iface.mainWindow().statusBar().showMessage( 'Processing {}'.format(self.windowTitle())) LOGGER.info('{st}\nProcessing {}'.format(self.windowTitle(), st='*' * 50)) self.send_to_messagebar( "Please wait.. QGIS will be locked... See log panel for progress.", level=QgsMessageBar.WARNING, duration=0, addToLog=False, core_QGIS=False, showLogPanel=True) # Add settings to log settingsStr = 'Parameters:---------------------------------------' settingsStr += '\n {:20}\t{}'.format( 'Image layer:', self.mcboRasterLayer.currentLayer().name()) settingsStr += '\n {:20}\t{}'.format('Image Band:', self.cboBand.currentText()) settingsStr += '\n {:20}\t{}'.format('Image nodata value:', self.spnNoDataVal.value()) if self.chkUsePoly.isChecked(): if self.chkUseSelected.isChecked(): settingsStr += '\n {:20}\t{} with {} selected features'.format( 'Layer:', self.mcboPolygonLayer.currentLayer().name(), len(self.mcboPolygonLayer.currentLayer(). selectedFeatures())) else: settingsStr += '\n {:20}\t{}'.format( 'Boundary layer:', self.mcboPolygonLayer.currentLayer().name()) if self.mFieldComboBox.currentField(): settingsStr += '\n {:20}\t{}'.format( 'Block ID field:', self.mFieldComboBox.currentField()) else: settingsStr += '\n {:20}\t{}'.format('Boundary layer:', '') settingsStr += '\n {:20}\t{}'.format('Block ID field:', '') settingsStr += '\n {:20}\t{}'.format('Resample pixel size: ', self.dsbPixelSize.value()) settingsStr += '\n {:30}\t{}'.format( 'Output Coordinate System:', self.lblOutCRS.text()) settingsStr += '\n {:30}\t{}\n'.format( 'Output Folder:', self.lneOutputFolder.text()) LOGGER.info(settingsStr) lyrRaster = self.mcboRasterLayer.currentLayer() if self.chkUsePoly.isChecked(): lyrBoundary = self.mcboPolygonLayer.currentLayer() if self.chkUseSelected.isChecked(): savePlyName = lyrBoundary.name() + '_poly.shp' filePoly = os.path.join(TEMPDIR, savePlyName) if os.path.exists(filePoly): removeFileFromQGIS(filePoly) QgsVectorFileWriter.writeAsVectorFormat(lyrBoundary, filePoly, "utf-8", lyrBoundary.crs(), "ESRI Shapefile", onlySelected=True) if self.DISP_TEMP_LAYERS: addVectorFileToQGIS(filePoly, layer_name=os.path.splitext( os.path.basename(filePoly))[0], group_layer_name='DEBUG', atTop=True) else: filePoly = lyrBoundary.source() band_num = [int(self.cboBand.currentText().replace('Band ', ''))] files = resample_bands_to_block( lyrRaster.source(), self.dsbPixelSize.value(), self.lneOutputFolder.text(), band_nums=band_num, image_epsg=int(lyrRaster.crs().authid().replace('EPSG:', '')), image_nodata=self.spnNoDataVal.value(), polygon_shapefile=filePoly if self.chkUsePoly.isChecked() else None, groupby=self.mFieldComboBox.currentField() if self.mFieldComboBox.currentField() else None, out_epsg=int(self.outQgsCRS.authid().replace('EPSG:', ''))) if self.chkAddToDisplay.isChecked(): for ea_file in files: removeFileFromQGIS(ea_file) addRasterFileToQGIS(ea_file, group_layer_name=os.path.basename( os.path.dirname(ea_file)), atTop=False) self.cleanMessageBars(True) self.fraMain.setDisabled(False) self.iface.mainWindow().statusBar().clearMessage() self.iface.messageBar().popWidget() QtGui.qApp.restoreOverrideCursor() return super(ResampleImageToBlockDialog, self).accept(*args, **kwargs) except Exception as err: QtGui.qApp.restoreOverrideCursor() self.iface.mainWindow().statusBar().clearMessage() self.cleanMessageBars(True) self.fraMain.setDisabled(False) self.send_to_messagebar(str(err), level=QgsMessageBar.CRITICAL, duration=0, addToLog=True, core_QGIS=False, showLogPanel=True, exc_info=sys.exc_info()) return False # leave dialog open
class GNSS3DCaptureDockWidget(QtGui.QDockWidget, FORM_CLASS): closingPlugin = pyqtSignal() def __init__(self, iface, parent=None): """Constructor.""" super(GNSS3DCaptureDockWidget, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) self.iface = iface self.initialize() def closeEvent(self, event): self.closingPlugin.emit() event.accept() def finishProcess(self): self.capturePointGroupBox.setEnabled(False) self.nameLineEdit.clear() self.numberLineEdit.clear() self.codeLineEdit.clear() self.firstCoordinateLineEdit.clear() self.secondCoordinateLineEdit.clear() self.heightAntennaLineEdit.clear() self.heightGpsLineEdit.clear() self.heightGroundLineEdit.clear() self.heightGeoidLineEdit.clear() self.heightFromGeoidLineEdit.clear() self.configurePushButton.setEnabled(True) self.startPushButton.setEnabled(False) self.finishPushButton.setEnabled(False) def getGeoidInterpolatedValue(self, gpsLongitude, gpsLatitude): geoidPoint = QgsPoint(gpsLongitude, gpsLatitude) geoidPoint = self.crsOperationFromGpsToGeoid.transform(geoidPoint) geoidHeight = constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE if not self.geoidModel.extent().contains(geoidPoint): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Point out of Geoid Model extension:\n", self.geoidModelFileName) msgBox.exec_() return geoidHeight firstCoordinate = geoidPoint.x() secondCoordinate = geoidPoint.y() dbl_column = (firstCoordinate - self.geoidMinimumFirstCoordinate ) / self.geoidStepFirstCoordinate dbl_row = (secondCoordinate - self.geoidMaximumSecondCoordinate ) / self.geoidStepSecondCoordinate inc_column = dbl_column - floor(dbl_column) inc_row = dbl_row - floor(dbl_row) f00 = self.getGeoidPixelValue(firstCoordinate, secondCoordinate) if f00 == constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE: return geoidHeight f10 = self.getGeoidPixelValue( firstCoordinate + self.geoidStepFirstCoordinate, secondCoordinate) if f10 == constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE: return geoidHeight f01 = self.getGeoidPixelValue( firstCoordinate, secondCoordinate + self.geoidStepSecondCoordinate) if f01 == constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE: return geoidHeight f11 = self.getGeoidPixelValue( firstCoordinate + self.geoidStepFirstCoordinate, secondCoordinate + self.geoidStepSecondCoordinate) if f11 == constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE: return geoidHeight geoidHeight = (1.0 - inc_row) * (1.0 - inc_column) * f00 geoidHeight += inc_column * (1.0 - inc_row) * f10 geoidHeight += (1.0 - inc_column) * inc_row * f01 geoidHeight += inc_column * inc_row * f11 return geoidHeight def getGeoidPixelValue(self, gpsLongitude, gpsLatitude): geoidPoint = QgsPoint(gpsLongitude, gpsLatitude) geoidPoint = self.crsOperationFromGpsToGeoid.transform(geoidPoint) geoidHeight = constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE if not self.geoidModel.extent().contains(geoidPoint): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Point out of Geoid Model extension:\n", self.geoidModelFileName) msgBox.exec_() return geoidHeight firstCoordinate = geoidPoint.x() secondCoordinate = geoidPoint.y() ident = self.geoidModel.dataProvider().identify( geoidPoint, QgsRaster.IdentifyFormatValue) if ident.isValid(): values = ident.results() geoidHeight = values[1] else: msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Error getting value in Geoid Model:\n", self.geoidModelFileName) msgBox.exec_() return geoidHeight def initialize(self): aux_path_plugin = 'python/plugins/' + constants.CONST_GNSS_3D_CAPTURE_NAME qgisUserDbFilePath = QgsApplication.qgisUserDbFilePath() self.path_plugin = os.path.join( QFileInfo(QgsApplication.qgisUserDbFilePath()).path(), aux_path_plugin) path_file_qsettings = self.path_plugin + '/' + constants.CONST_GNSS_3D_CAPTURE_SETTINGS_FILE_NAME self.settings = QSettings(path_file_qsettings, QSettings.IniFormat) self.lastPath = self.settings.value("last_path") if not self.lastPath: self.lastPath = QDir.currentPath() self.settings.setValue("last_path", self.lastPath) self.settings.sync() self.crsAuthId = self.settings.value("crsAuthId") if not self.crsAuthId: self.crsAuthId = self.iface.mapCanvas().mapRenderer( ).destinationCrs().authid() self.settings.setValue("crsAuthId", self.crsAuthId) self.settings.sync() self.crs = QgsCoordinateReferenceSystem() self.crs.createFromUserInput(self.crsAuthId) if self.crs.geographicFlag(): self.firstCoordinateLabel.setText("Longitude") self.secondCoordinateLabel.setText("Latitude") else: self.firstCoordinateLabel.setText("Easting") self.secondCoordinateLabel.setText("Northing") self.iface.mapCanvas().mapRenderer().setProjectionsEnabled(True) self.startPushButton.setEnabled(False) self.finishPushButton.setEnabled(False) self.capturePointGroupBox.setEnabled(False) QtCore.QObject.connect(self.configurePushButton, QtCore.SIGNAL("clicked(bool)"), self.selectConfigure) # QtCore.QObject.connect(self.crsPushButton,QtCore.SIGNAL("clicked(bool)"),self.selectCrs) # QtCore.QObject.connect(self.geoidCheckBox,QtCore.SIGNAL("clicked(bool)"),self.activateGeoid) QtCore.QObject.connect(self.startPushButton, QtCore.SIGNAL("clicked(bool)"), self.startProcess) QtCore.QObject.connect(self.updatePositionPushButton, QtCore.SIGNAL("clicked(bool)"), self.updatePosition) QtCore.QObject.connect(self.finishPushButton, QtCore.SIGNAL("clicked(bool)"), self.finishProcess) QtCore.QObject.connect(self.savePointPushButton, QtCore.SIGNAL("clicked(bool)"), self.savePoint) QtCore.QObject.connect(self.codePushButton, QtCore.SIGNAL("clicked(bool)"), self.selectCode) QtCore.QObject.connect(self.namePushButton, QtCore.SIGNAL("clicked(bool)"), self.selectName) QtCore.QObject.connect(self.numberPushButton, QtCore.SIGNAL("clicked(bool)"), self.selectNumber) QtCore.QObject.connect(self.heightAntennaPushButton, QtCore.SIGNAL("clicked(bool)"), self.selectAntennaHeight) self.pointNumbers = [] #self.configureDialog = None self.configureDialog = GNSS3DCaptureDialog(self.iface, self.lastPath, self.crs) self.num_format = re.compile(r'^\-?[1-9][0-9]*\.?[0-9]*') def savePoint(self): connectionRegistry = QgsGPSConnectionRegistry().instance() connectionList = connectionRegistry.connectionList() if connectionList == []: msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText( "GPS connection not detected.\nConnect a GPS and try again") msgBox.exec_() return csvFile = QFile(self.csvFileName) if not csvFile.open(QIODevice.Append | QIODevice.Text): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Error opening for writting file:\n" + self.csvFileName) msgBox.exec_() return csvTextStream = QTextStream(csvFile) csvTextStream << "\n" fieldValues = {} fieldNumber = 0 listFieldValues = [] if self.useName: name = self.nameLineEdit.text() csvTextStream << name << "," #fieldValues[fieldNumber]=QVariant(name) fieldValues[fieldNumber] = name fieldNumber = fieldNumber + 1 listFieldValues.append(name) if self.useNumber: number = self.numberLineEdit.text() csvTextStream << number << "," #fieldValues[fieldNumber]=QVariant(number) fieldValues[fieldNumber] = number fieldNumber = fieldNumber + 1 listFieldValues.append(number) GPSInfo = connectionList[0].currentGPSInformation() firstCoordinate = GPSInfo.longitude secondCoordinate = GPSInfo.latitude pointCrsGps = QgsPoint(firstCoordinate, secondCoordinate) pointCrs = self.crsOperationFromGps.transform(pointCrsGps) firstCoordinate = pointCrs.x() secondCoordinate = pointCrs.y() if self.crs.geographicFlag(): strFirstCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_LONGITUDE_PRECISION.format( firstCoordinate) strSecondCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_LATITUDE_PRECISION.format( secondCoordinate) else: strFirstCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_EASTING_PRECISION.format( firstCoordinate) strSecondCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_NORTHING_PRECISION.format( secondCoordinate) csvTextStream << strFirstCoordinate << "," csvTextStream << strSecondCoordinate #fieldValues[fieldNumber]=QVariant(firstCoordinate) fieldValues[fieldNumber] = firstCoordinate listFieldValues.append(firstCoordinate) fieldNumber = fieldNumber + 1 #fieldValues[fieldNumber]=QVariant(secondCoordinate) fieldValues[fieldNumber] = secondCoordinate listFieldValues.append(secondCoordinate) fieldNumber = fieldNumber + 1 if self.useHeight: antennaHeight = float(self.heightAntennaLineEdit.text()) height = GPSInfo.elevation height = height - antennaHeight if self.useGeoidModel: geoidHeight = self.getGeoidInterpolatedValue( GPSInfo.longitude, GPSInfo.latitude) if geoidHeight == constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE: return height = height - geoidHeight strHeight = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_HEIGHT_PRECISION.format( height) csvTextStream << "," << strHeight #fieldValues[fieldNumber]=QVariant(height) fieldValues[fieldNumber] = height listFieldValues.append(height) fieldNumber = fieldNumber + 1 if self.useCode: code = self.codeLineEdit.text() csvTextStream << "," << code #fieldValues[fieldNumber]=QVariant(code) fieldValues[fieldNumber] = code listFieldValues.append(code) csvFile.close() fet = QgsFeature() fet.setGeometry( QgsGeometry.fromPoint(QgsPoint(firstCoordinate, secondCoordinate))) #fet.setAttributeMap(fieldValues) fet.setAttributes(listFieldValues) self.memoryLayerDataProvider.addFeatures([fet]) self.memoryLayer.commitChanges() self.memoryLayerName.triggerRepaint() if self.useNumber: self.pointNumbers.append(int(number)) candidateValue = self.pointNumbers[len(self.pointNumbers) - 1] + 1 if self.pointNumbers.count(candidateValue) != 0: control = True while control: candidateValue = candidateValue + 1 if self.pointNumbers.count(candidateValue) == 0: control = False self.numberLineEdit.setText(str(candidateValue)) self.accept() def selectCode(self): oldText = self.codeLineEdit.text() label = "Input Point Code:" title = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_WINDOW_TITLE [text, ok] = QInputDialog.getText(self, title, label, QLineEdit.Normal, oldText) if ok and text: text = text.strip() if not text == oldText: self.codeLineEdit.setText(text) def selectAntennaHeight(self): strCandidateValue = self.heightAntennaLineEdit.text() label = "Input Antenna Height:" title = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_WINDOW_TITLE ok = False while not ok: [text, ok] = QInputDialog.getText(self, title, label, QLineEdit.Normal, strCandidateValue) if ok and text: value = 0.0 text = text.strip() if text.isdigit() or re.match(self.num_format, text): value = float(text) if (value < constants. CONST_GNSS_3D_CAPTURE_SAVE_POINT_ANTENNA_HEIGHT_MINIMUM_VALUE or value > constants. CONST_GNSS_3D_CAPTURE_SAVE_POINT_ANTENNA_HEIGHT_MAXIMUM_VALUE ): ok = False else: ok = False if ok: strValue = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_ANTENNA_HEIGHT_PRECISION.format( value) self.heightAntennaLineEdit.setText(strValue) self.updatePosition() else: if not ok: ok = True def selectConfigure(self): # if self.configureDialog == None: # self.configureDialog = GNSS3DCaptureDialog(self.iface,self.lastPath,self.crs) # self.configureDialog.show() # show the dialog # result = self.configureDialog.exec_() # Run the dialog # yo =1 # else: # self.configureDialog.show() # show the dialog # result = self.configureDialog.exec_() # Run the dialog # yo =1 # if self.configureDialog.isOk(): self.configureDialog.show() # show the dialog result = self.configureDialog.exec_() # Run the dialog self.csvFileName = self.configureDialog.getCsvFileName() self.lastPath = self.configureDialog.getLastPath() self.crs = self.configureDialog.getCrs() self.useCode = self.configureDialog.getUseCode() self.useName = self.configureDialog.getUseName() self.useHeight = self.configureDialog.getUseHeight() self.useNumber = self.configureDialog.getUseNumber() self.useGeoidModel = self.configureDialog.getUseGeoidModel() self.geoidModelFileName = self.configureDialog.getGeoidModelFileName() if self.crs.isValid(): if self.crs.geographicFlag(): self.firstCoordinateLabel.setText("Longitude") self.secondCoordinateLabel.setText("Latitude") else: self.firstCoordinateLabel.setText("Easting") self.secondCoordinateLabel.setText("Northing") crsAuthId = self.crs.authid() self.settings.setValue("crsAuthId", crsAuthId) self.settings.sync() if self.lastPath: self.settings.setValue("last_path", self.lastPath) self.settings.sync() if self.configureDialog.getIsOk(): self.startPushButton.setEnabled(True) else: self.startPushButton.setEnabled(False) def selectName(self): oldText = self.nameLineEdit.text() label = "Input Point Name:" title = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_WINDOW_TITLE [text, ok] = QInputDialog.getText(self, title, label, QLineEdit.Normal, oldText) if ok and text: text = text.strip() if not text == oldText: self.nameLineEdit.setText(text) def selectNumber(self): if self.pointNumbers == []: candidateValue = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_FIRST_POINT_NUMBER else: candidateValue = self.pointNumbers(len(self.pointNumbers) - 1) label = "Input Point Number:" title = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_WINDOW_TITLE ok = False while not ok: [text, ok] = QInputDialog.getText(self, title, label, QLineEdit.Normal, str(candidateValue)) if ok and text: text = text.strip() if not text.isdigit(): ok = False else: value = int(text) if (value < constants. CONST_GNSS_3D_CAPTURE_SAVE_POINT_POINT_NUMBER_MINIMUM_VALUE or value > constants. CONST_GNSS_3D_CAPTURE_SAVE_POINT_POINT_NUMBER_MAXIMUM_VALUE ): ok = False if ok: self.numberLineEdit.setText(text) else: if not ok: ok = True def startProcess(self): connectionRegistry = QgsGPSConnectionRegistry().instance() connectionList = connectionRegistry.connectionList() if connectionList == []: msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText( "GPS connection not detected.\nConnect a GPS and try again") msgBox.exec_() return GPSInfo = connectionList[0].currentGPSInformation() self.capturePointGroupBox.setEnabled(False) if not self.configureDialog.getIsOk(): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("The configuration is not valid") msgBox.exec_() return if self.useCode: self.codePushButton.setEnabled(True) self.codeLineEdit.setEnabled(True) else: self.codePushButton.setEnabled(False) self.codeLineEdit.setEnabled(False) self.codeLineEdit.clear() if self.useName: self.namePushButton.setEnabled(True) self.nameLineEdit.setEnabled(True) else: self.namePushButton.setEnabled(False) self.nameLineEdit.setEnabled(False) self.nameLineEdit.clear() if self.useNumber: self.numberPushButton.setEnabled(True) self.numberLineEdit.setEnabled(True) else: self.numberPushButton.setEnabled(False) self.numberLineEdit.setEnabled(False) self.numberLineEdit.clear() if self.useHeight: self.heightAntennaPushButton.setEnabled(True) self.heightAntennaLineEdit.setEnabled(True) self.antennaHeight = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_ANTENNA_HEIGHT_DEFAULT_VALUE strAntennaHeigth = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_ANTENNA_HEIGHT_PRECISION.format( self.antennaHeight) self.heightAntennaLineEdit.setText(strAntennaHeigth) self.heightGpsLabel.setEnabled(True) self.heightGpsLineEdit.setEnabled(True) self.heightGroundLabel.setEnabled(True) self.heightGroundLineEdit.setEnabled(True) if self.useGeoidModel and self.geoidModelFileName: self.heightGeoidLabel.setEnabled(True) self.heightGeoidLineEdit.setEnabled(True) self.heightFromGeoidLabel.setEnabled(True) self.heightFromGeoidLineEdit.setEnabled(True) else: self.heightGeoidLabel.setEnabled(False) self.heightGeoidLineEdit.setEnabled(False) self.heightGeoidLineEdit.clear() self.heightFromGeoidLabel.setEnabled(False) self.heightFromGeoidLineEdit.setEnabled(False) self.heightFromGeoidLineEdit.clear() else: self.heightAntennaPushButton.setEnabled(False) self.heightAntennaLineEdit.setEnabled(False) self.heightAntennaLineEdit.clear() self.heightGpsLabel.setEnabled(False) self.heightGpsLineEdit.setEnabled(False) self.heightGpsLineEdit.clear() self.heightGroundLabel.setEnabled(False) self.heightGroundLineEdit.setEnabled(False) self.heightGroundLineEdit.clear() self.heightGeoidLabel.setEnabled(False) self.heightGeoidLineEdit.setEnabled(False) self.heightGeoidLineEdit.clear() self.heightFromGeoidLabel.setEnabled(False) self.heightFromGeoidLineEdit.setEnabled(False) self.heightFromGeoidLineEdit.clear() fileName = self.csvFileName if not fileName: msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("You must select CSV file") msgBox.exec_() return strDateTime = "" if QFile.exists(fileName): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) text = "Exists CSV file:\n" + fileName msgBox.setText(text) msgBox.setInformativeText( "Do you want to rename it with current date an time?") msgBox.setStandardButtons(QMessageBox.Ok | QMessageBox.Discard | QMessageBox.Cancel) msgBox.setDefaultButton(QMessageBox.Ok) ret = msgBox.exec_() if ret == QMessageBox.Ok: dateTime = QDateTime.currentDateTime() strDateTime = dateTime.toString("yyyy-MM-dd_HH-mm-ss") fileInfo = QFileInfo(fileName) filePath = fileInfo.absolutePath() fileNameWithoutExtension = fileInfo.completeBaseName() fileExtension = fileInfo.completeSuffix() newFileName = filePath + "/" + fileNameWithoutExtension + "_" + strDateTime + "." + fileExtension if not QFile.copy(fileName, newFileName): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Warning) msgBox.setWindowTitle( constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setWindowTitle( constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Error copying existing file:\n" + fileName + "\n" + newFileName) msgBox.exec_() return if not self.crs.isValid(): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("You must select the output CRS") msgBox.exec_() return if self.useGeoidModel and self.geoidModelFileName == constants.CONST_GNSS_3D_CAPTURE_COMBOBOX_NO_SELECT_OPTION: msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText( "If you select substract geoide height \n you must select a geoid model" ) msgBox.exec_() return csvFile = QFile(fileName) if not csvFile.open(QIODevice.WriteOnly | QIODevice.Text): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Error opening for writting file:\n" + fileName) msgBox.exec_() return csvTextStream = QTextStream(csvFile) fileInfo = QFileInfo(fileName) self.memoryLayerName = fileInfo.completeBaseName() existsMemoryLayer = None for lyr in QgsMapLayerRegistry.instance().mapLayers().values(): if lyr.name() == self.memoryLayerName: existsMemoryLayer = lyr break if existsMemoryLayer != None: newMemoryLayerName = self.memoryLayerName + "_" + strDateTime existsMemoryLayer.setLayerName(newMemoryLayerName) memoryLayerTypeAndCrs = "Point?crs=" + self.crs.authid() #EPSG:4326" self.memoryLayer = QgsVectorLayer(memoryLayerTypeAndCrs, self.memoryLayerName, "memory") self.memoryLayerDataProvider = self.memoryLayer.dataProvider() memoryLayerFields = [] # add fields firstField = True if self.useName: csvTextStream << "Name" firstField = False memoryLayerFields.append(QgsField("Name", QVariant.String)) if self.useNumber: if not firstField: csvTextStream << "," else: firstField = False csvTextStream << "Number" memoryLayerFields.append(QgsField("Number", QVariant.Int)) if not firstField: csvTextStream << "," else: firstField = False if not self.crs.geographicFlag(): csvTextStream << "Easting" csvTextStream << "," << "Northing" memoryLayerFields.append(QgsField("Easting", QVariant.Double)) memoryLayerFields.append(QgsField("Northing", QVariant.Double)) else: csvTextStream << "Longitude" csvTextStream << "," << "Latitude" memoryLayerFields.append(QgsField("Longitude", QVariant.Double)) memoryLayerFields.append(QgsField("Latitude", QVariant.Double)) if self.useHeight: csvTextStream << "," << "Height" memoryLayerFields.append(QgsField("Height", QVariant.Double)) if self.useCode: csvTextStream << "," << "Code" memoryLayerFields.append(QgsField("Code", QVariant.String)) csvFile.close() self.memoryLayerDataProvider.addAttributes(memoryLayerFields) # self.memoryLayerDataProvider.addAttributes([QgsField("Name", QVariant.String), # QgsField("Number", QVariant.String), # QgsField("FirstCoordinate", QVariant.Double), # QgsField("SecondCoordinate", QVariant.Double), # QgsField("Height", QVariant.Double), # QgsField("Code", QVariant.Int)]) self.memoryLayer.startEditing() self.memoryLayer.commitChanges() qmlFileName = self.path_plugin + "/" + constants.CONST_GNSS_3D_CAPTURE_QML_TEMPLATES_FOLDER + "/" if self.useName: qmlFileName += constants.CONST_GNSS_3D_CAPTURE_QML_TEMPLATES_FOLDER_QML_POINT_NAME_Z elif self.useNumber: qmlFileName += constants.CONST_GNSS_3D_CAPTURE_QML_TEMPLATES_FOLDER_QML_POINT_NUMBER_Z else: qmlFileName += constants.CONST_GNSS_3D_CAPTURE_QML_TEMPLATES_FOLDER_QML_POINT_Z self.memoryLayer.loadNamedStyle(qmlFileName) QgsMapLayerRegistry.instance().addMapLayer(self.memoryLayer) epsgCodeGps = constants.CONST_GNSS_3D_CAPTURE_EPSG_CODE_GPS self.crsGps = QgsCoordinateReferenceSystem(epsgCodeGps) if not self.crsGps.isValid(): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Error creating CRS by EPSG Code: " + str(epsgCodeGps)) msgBox.exec_() self.isValid = False return self.crsOperationFromGps = QgsCoordinateTransform( self.crsGps, self.crs) if self.useHeight: if self.useGeoidModel: if not QFile.exists(self.geoidModelFileName): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle( constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Geoid Model file not exists:\n" + self.geoidModelFileName) msgBox.exec_() self.isValid = False return geoidModelFileInfo = QFileInfo(self.geoidModelFileName) geoidModelPath = geoidModelFileInfo.filePath() geoidModelBaseName = geoidModelFileInfo.baseName() self.geoidModel = QgsRasterLayer(geoidModelPath, geoidModelBaseName) self.crsGeoidModel = self.geoidModel.crs() if not self.crsGeoidModel.isValid(): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle( constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Error getting Geoid Model CRS:\n" + self.geoidModelFileName) msgBox.exec_() self.isValid = False return self.geoidStepFirstCoordinate = self.geoidModel.rasterUnitsPerPixelX( ) # debe ser positivo self.geoidStepSecondCoordinate = 1.0 * self.geoidModel.rasterUnitsPerPixelX( ) # debe ser positivo self.geoidExtend = self.geoidModel.dataProvider().extent() self.geoidMinimumFirstCoordinate = self.geoidExtend.xMinimum() self.geoidMaximumSecondCoordinate = self.geoidExtend.yMaximum() self.crsOperationFromGpsToGeoid = QgsCoordinateTransform( self.crsGps, self.crsGeoidModel) self.capturePointGroupBox.setEnabled(True) self.configurePushButton.setEnabled(False) self.startPushButton.setEnabled(False) self.finishPushButton.setEnabled(True) if self.useNumber: strFirstNumber = str( constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_FIRST_POINT_NUMBER) self.numberLineEdit.setText(strFirstNumber) self.updatePosition() def updatePosition(self): connectionRegistry = QgsGPSConnectionRegistry().instance() connectionList = connectionRegistry.connectionList() if connectionList == []: msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText( "GPS connection not detected.\nConnect a GPS and try again") msgBox.exec_() return GPSInfo = connectionList[0].currentGPSInformation() firstCoordinate = GPSInfo.longitude secondCoordinate = GPSInfo.latitude pointCrsGps = QgsPoint(firstCoordinate, secondCoordinate) pointCrs = self.crsOperationFromGps.transform(pointCrsGps) firstCoordinate = pointCrs.x() secondCoordinate = pointCrs.y() if self.crs.geographicFlag(): strFirstCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_LONGITUDE_PRECISION.format( firstCoordinate) strSecondCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_LATITUDE_PRECISION.format( secondCoordinate) else: strFirstCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_EASTING_PRECISION.format( firstCoordinate) strSecondCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_NORTHING_PRECISION.format( secondCoordinate) self.firstCoordinateLineEdit.setText(strFirstCoordinate) self.secondCoordinateLineEdit.setText(strSecondCoordinate) antennaHeight = float(self.heightAntennaLineEdit.text()) if self.useHeight: height = GPSInfo.elevation heightGround = height - antennaHeight strHeight = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_HEIGHT_PRECISION.format( height) self.heightGpsLineEdit.setText(strHeight) strHeightGround = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_HEIGHT_PRECISION.format( heightGround) self.heightGroundLineEdit.setText(strHeightGround) if self.useGeoidModel: geoidHeight = self.getGeoidInterpolatedValue( GPSInfo.longitude, GPSInfo.latitude) if geoidHeight == constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE: return strGeoidHeight = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_GEOID_HEIGHT_PRECISION.format( geoidHeight) heightFromGeoid = heightGround - geoidHeight strHeightFromGeoid = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_HEIGHT_FROM_GEOID_PRECISION.format( heightFromGeoid) self.heightGeoidLineEdit.setText(strGeoidHeight) self.heightFromGeoidLineEdit.setText(strHeightFromGeoid)
class StripTrialPointsDialog(QtGui.QDialog, FORM_CLASS): """Extract statistics from a list of rasters at set locations.""" toolKey = 'StripTrialPointsDialog' def __init__(self, iface, parent=None): super(StripTrialPointsDialog, self).__init__(parent) # Set up the user interface from Designer. self.setupUi(self) self.iface = iface self.DISP_TEMP_LAYERS = read_setting(PLUGIN_NAME + '/DISP_TEMP_LAYERS', bool) self.DEBUG = config.get_debug_mode() # Catch and redirect python errors directed at the log messages python error tab. QgsMessageLog.instance().messageReceived.connect(errorCatcher) if not os.path.exists(TEMPDIR): os.mkdir(TEMPDIR) # Setup for validation messagebar on gui----------------------------- self.messageBar = QgsMessageBar( self) # leave this message bar for bailouts self.validationLayout = QtGui.QFormLayout(self) # new layout to gui if isinstance(self.layout(), (QtGui.QFormLayout, QtGui.QGridLayout)): # create a validation layout so multiple messages can be added and cleaned up. self.layout().insertRow(0, self.validationLayout) self.layout().insertRow(0, self.messageBar) else: self.layout().insertWidget( 0, self.messageBar) # for use with Vertical/horizontal layout box self.outQgsCRS = None self.exclude_map_layers() # self.updateUseSelected() self.autoSetCoordinateSystem() # GUI Runtime Customisation ----------------------------------------------- self.setWindowIcon( QtGui.QIcon(':/plugins/pat/icons/icon_stripTrialPoints.svg')) self.chkUseSelected.setChecked(False) self.chkUseSelected.hide() self.chkSaveLinesFile.setChecked(False) def cleanMessageBars(self, AllBars=True): """Clean Messages from the validation layout. Args: AllBars (bool): Remove All bars including those which haven't timed-out. Defaults to True """ layout = self.validationLayout for i in reversed(range(layout.count())): # when it timed out the row becomes empty.... if layout.itemAt(i).isEmpty(): # .removeItem doesn't always work. so takeAt(pop) it instead item = layout.takeAt(i) elif AllBars: # ie remove all item = layout.takeAt(i) # also have to remove any widgets associated with it. if item.widget() is not None: item.widget().deleteLater() def send_to_messagebar(self, message, title='', level=QgsMessageBar.INFO, duration=5, exc_info=None, core_QGIS=False, addToLog=False, showLogPanel=False): """ Add a message to the forms message bar. Args: message (str): Message to display title (str): Title of message. Will appear in bold. Defaults to '' level (QgsMessageBarLevel): The level of message to log. Defaults to QgsMessageBar.INFO duration (int): Number of seconds to display message for. 0 is no timeout. Defaults to 5 core_QGIS (bool): Add to QGIS interface rather than the dialog addToLog (bool): Also add message to Log. Defaults to False showLogPanel (bool): Display the log panel exc_info () : Information to be used as a traceback if required """ if core_QGIS: newMessageBar = self.iface.messageBar() else: newMessageBar = QgsMessageBar(self) widget = newMessageBar.createMessage(title, message) if showLogPanel: button = QPushButton(widget) button.setText('View') button.setContentsMargins(0, 0, 0, 0) button.setFixedWidth(35) button.pressed.connect(openLogPanel) widget.layout().addWidget(button) newMessageBar.pushWidget(widget, level, duration=duration) if not core_QGIS: rowCount = self.validationLayout.count() self.validationLayout.insertRow(rowCount + 1, newMessageBar) if addToLog: if level == 1: # 'WARNING': LOGGER.warning(message) elif level == 2: # 'CRITICAL': # Add a traceback to log only for bailouts only if exc_info is not None: exc_type, exc_value, exc_traceback = sys.exc_info() mess = str(traceback.format_exc()) message = message + '\n' + mess LOGGER.critical(message) else: # INFO = 0 LOGGER.info(message) def exclude_map_layers(self): """ Run through all loaded layers to find ones which should be excluded. In this case exclude services.""" exVlayer_list = [] for layer in self.iface.legendInterface().layers(): if layer.type() == QgsMapLayer.VectorLayer: if layer.providerType() != 'ogr': exVlayer_list.append(layer) if len(exVlayer_list) > 0: self.mcboLineLayer.setExceptedLayerList(exVlayer_list) def updateUseSelected(self): """Update use selected checkbox if active layer has a feature selection""" self.chkUseSelected.setChecked(False) if self.mcboLineLayer.count() == 0: return line_lyr = self.mcboLineLayer.currentLayer() self.mFieldComboBox.setLayer(line_lyr) if len(line_lyr.selectedFeatures()) > 0: self.chkUseSelected.setText( 'Use the {} selected feature(s) ?'.format( len(line_lyr.selectedFeatures()))) self.chkUseSelected.setEnabled(True) else: self.chkUseSelected.setText('No features selected') self.chkUseSelected.setEnabled(False) def autoSetCoordinateSystem(self): if self.mcboLineLayer.count() == 0: return self.cleanMessageBars() line_lyr = self.mcboLineLayer.currentLayer() line_utm_crs = crs.getProjectedCRSForXY( line_lyr.extent().xMinimum(), line_lyr.extent().yMinimum(), int(line_lyr.crs().authid().replace('EPSG:', ''))) self.outQgsCRS = None if line_utm_crs is not None: line_crs = QgsCoordinateReferenceSystem('EPSG:{}'.format( line_utm_crs.epsg_number)) self.outQgsCRS = line_crs if self.outQgsCRS is not None: self.lblOutCRS.setText('{} - {}'.format( self.outQgsCRS.description(), self.outQgsCRS.authid())) self.lblOutCRSTitle.setStyleSheet('color:black') self.lblOutCRS.setStyleSheet('color:black') else: self.lblOutCRSTitle.setStyleSheet('color:red') self.lblOutCRS.setStyleSheet('color:red') self.lblOutCRS.setText('Unspecified') self.send_to_messagebar( 'Auto detect coordinate system Failed. Check coordinate system of input raster layer', level=QgsMessageBar.CRITICAL, duration=5) return def on_mcboLineLayer_layerChanged(self): # self.updateUseSelected() self.autoSetCoordinateSystem() @QtCore.pyqtSlot(int) def on_chkUseSelected_stateChanged(self, state): if self.chkUseSelected.isChecked(): self.chkUsePoly.setChecked(True) @QtCore.pyqtSlot(name='on_cmdOutCRS_clicked') def on_cmdOutCRS_clicked(self): dlg = QgsGenericProjectionSelector(self) dlg.setMessage(self.tr('Select coordinate system')) if dlg.exec_(): if dlg.selectedAuthId() != '': self.outQgsCRS = QgsCoordinateReferenceSystem( dlg.selectedAuthId()) if self.outQgsCRS.geographicFlag(): self.outQgsCRS = None self.send_to_messagebar(unicode( self. tr("Geographic coordinate systems are not allowed. Resetting to default.." )), level=QgsMessageBar.WARNING, duration=5) else: self.outQgsCRS = None if self.outQgsCRS is None: self.autoSetCoordinateSystem() self.lblOutCRSTitle.setStyleSheet('color:black') self.lblOutCRS.setStyleSheet('color:black') self.lblOutCRS.setText( self.tr('{} - {}'.format(self.outQgsCRS.description(), self.outQgsCRS.authid()))) @QtCore.pyqtSlot(name='on_cmdSavePointsFile_clicked') def on_cmdSavePointsFile_clicked(self): self.messageBar.clearWidgets() lastFolder = read_setting(PLUGIN_NAME + "/" + self.toolKey + "/LastOutFolder") if lastFolder is None or not os.path.exists(lastFolder): lastFolder = read_setting(PLUGIN_NAME + "/BASE_OUT_FOLDER") filename = self.mcboLineLayer.currentText() + '_strip-trial-points' s = save_as_dialog(self, self.tr("Save As"), self.tr("ESRI Shapefile") + " (*.shp);;", default_name=os.path.join(lastFolder, filename)) if s == '' or s is None: return s = os.path.normpath(s) write_setting(PLUGIN_NAME + "/" + self.toolKey + "/LastOutFolder", os.path.dirname(s)) self.lneSavePointsFile.setText(s) self.lblSavePointsFile.setStyleSheet('color:black') self.lneSavePointsFile.setStyleSheet('color:black') @QtCore.pyqtSlot(int) def on_chkSaveLinesFile_stateChanged(self, state): self.lneSaveLinesFile.setEnabled(state) if state: lastFolder = read_setting(PLUGIN_NAME + "/" + self.toolKey + "/LastOutFolder") if lastFolder is None or not os.path.exists(lastFolder): lastFolder = read_setting(PLUGIN_NAME + "/BASE_OUT_FOLDER") if self.lneSavePointsFile.text() == '': filename = os.path.join( lastFolder, self.mcboLineLayer.currentText() + '_strip-trial-lines.shp') else: path, file = os.path.split(self.lneSavePointsFile.text()) file, ext = os.path.splitext(file) filename = os.path.join( path, file.replace('-points', '') + '-lines' + ext) self.lneSaveLinesFile.setText(filename) self.chkSaveLinesFile.setStyleSheet('color:black') self.lneSaveLinesFile.setStyleSheet('color:black') else: self.lneSaveLinesFile.setText('') @QtCore.pyqtSlot(name='on_cmdSaveLinesFile_clicked') def on_cmdSaveLinesFile_clicked(self): self.messageBar.clearWidgets() lastFolder = read_setting(PLUGIN_NAME + "/" + self.toolKey + "/LastOutFolder") if lastFolder is None or not os.path.exists(lastFolder): lastFolder = read_setting(PLUGIN_NAME + "/BASE_OUT_FOLDER") if self.lneSaveLinesFile.text() != '': filename = self.lneSaveLinesFile.text() elif self.lneSavePointsFile.text() == '': filename = os.path.join( lastFolder, self.mcboLineLayer.currentText() + '_strip-trial-lines') else: path, file = os.path.split(self.lneSavePointsFile.text()) file, ext = os.path.splitext(file) filename = os.path.join( path, file.replace('-points', '') + '-lines' + ext) s = save_as_dialog(self, self.tr("Save As"), self.tr("ESRI Shapefile") + " (*.shp);;", default_name=os.path.join(lastFolder, filename)) if s == '' or s is None: return s = os.path.normpath(s) write_setting(PLUGIN_NAME + "/" + self.toolKey + "/LastOutFolder", os.path.dirname(s)) self.chkSaveLinesFile.setChecked(True) self.lneSaveLinesFile.setText(s) self.chkSaveLinesFile.setStyleSheet('color:black') self.lneSaveLinesFile.setStyleSheet('color:black') def validate(self): """Check to see that all required gui elements have been entered and are valid.""" self.messageBar.clearWidgets() self.cleanMessageBars(AllBars=True) try: errorList = [] if self.mcboLineLayer.currentLayer() is None: self.lblLineLayer.setStyleSheet('color:red') errorList.append(self.tr("Input line layer required.")) else: self.lblLineLayer.setStyleSheet('color:black') if self.dsbDistBtwnPoints.value() <= 0: self.lblDistBtwnPoints.setStyleSheet('color:red') errorList.append( self.tr("Distance between points must be greater than 0.")) else: self.lblDistBtwnPoints.setStyleSheet('color:black') if self.dsbLineOffsetDist.value() <= 0: self.lblLineOffsetDist.setStyleSheet('color:red') errorList.append( self.tr("Line offset distance must be greater than 0")) else: self.lblLineOffsetDist.setStyleSheet('color:black') if self.outQgsCRS is None: self.lblOutCRSTitle.setStyleSheet('color:red') self.lblOutCRS.setStyleSheet('color:red') errorList.append( self.tr("Select output projected coordinate system")) else: if self.outQgsCRS.geographicFlag(): self.lblOutCRSTitle.setStyleSheet('color:red') self.lblOutCRS.setStyleSheet('color:red') errorList.append( self. tr("Output projected coordinate system (not geographic) required" )) else: self.lblOutCRSTitle.setStyleSheet('color:black') self.lblOutCRS.setStyleSheet('color:black') if self.lneSavePointsFile.text() == '': self.lblSavePointsFile.setStyleSheet('color:red') errorList.append(self.tr("Save points shapefile")) elif not os.path.exists( os.path.dirname(self.lneSavePointsFile.text())): self.lneSavePointsFile.setStyleSheet('color:red') self.lblSavePointsFile.setStyleSheet('color:red') errorList.append( self.tr("Output shapefile folder cannot be found")) else: self.lblSavePointsFile.setStyleSheet('color:black') self.lneSavePointsFile.setStyleSheet('color:black') if self.chkSaveLinesFile.isChecked(): if self.lneSaveLinesFile.text() == '': self.chkSaveLinesFile.setStyleSheet('color:red') errorList.append(self.tr("Save lines shapefile")) elif not os.path.exists( os.path.dirname(self.lneSaveLinesFile.text())): self.lneSaveLinesFile.setStyleSheet('color:red') errorList.append( self.tr("Output shapefile folder cannot be found")) else: self.chkSaveLinesFile.setStyleSheet('color:black') self.lneSaveLinesFile.setStyleSheet('color:black') else: self.chkSaveLinesFile.setStyleSheet('color:black') self.lneSaveLinesFile.setStyleSheet('color:black') if len(errorList) > 0: raise ValueError(errorList) except ValueError as e: self.cleanMessageBars(True) if len(errorList) > 0: for i, ea in enumerate(errorList): self.send_to_messagebar(unicode(ea), level=QgsMessageBar.WARNING, duration=(i + 1) * 5) return False return True def accept(self, *args, **kwargs): try: if not self.validate(): return False # disable form via a frame, this will still allow interaction with the message bar self.fraMain.setDisabled(True) # clean gui and Qgis messagebars self.cleanMessageBars(True) # Change cursor to Wait cursor QtGui.qApp.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) self.iface.mainWindow().statusBar().showMessage( 'Processing {}'.format(self.windowTitle())) LOGGER.info('{st}\nProcessing {}'.format(self.windowTitle(), st='*' * 50)) self.send_to_messagebar( "Please wait.. QGIS will be locked... See log panel for progress.", level=QgsMessageBar.WARNING, duration=0, addToLog=False, core_QGIS=False, showLogPanel=True) # Add settings to log settingsStr = 'Parameters:---------------------------------------' settingsStr += '\n {:20}\t{}'.format( 'Line layer:', self.mcboLineLayer.currentLayer().name()) settingsStr += '\n {:20}\t{}'.format( 'Distance between points (m):', self.dsbDistBtwnPoints.value()) settingsStr += '\n {:20}\t{}'.format( 'Line offset distance (m):', self.dsbLineOffsetDist.value()) if self.chkUseSelected.isChecked(): settingsStr += '\n {:20}\t{} with {} selected features'.format( 'Layer:', self.mcboLineLayer.currentLayer().name(), len(self.mcboLineLayer.currentLayer().selectedFeatures())) settingsStr += '\n {:30}\t{}'.format( 'Output coordinate system:', self.lblOutCRS.text()) settingsStr += '\n {:30}\t{}'.format( 'Output points :', self.lneSavePointsFile.text()) if self.chkSaveLinesFile.isChecked(): settingsStr += '\n {:30}\t{}\n'.format( 'Output points :', self.chkSaveLinesFile.text()) LOGGER.info(settingsStr) lyr_line = self.mcboLineLayer.currentLayer() if self.chkUseSelected.isChecked(): line_shapefile = os.path.join(TEMPDIR, lyr_line.name() + '_lines.shp') if os.path.exists(line_shapefile): removeFileFromQGIS(line_shapefile) QgsVectorFileWriter.writeAsVectorFormat(lyr_line, line_shapefile, "utf-8", self.outQgsCRS, "ESRI Shapefile", onlySelected=True) if self.DISP_TEMP_LAYERS: addVectorFileToQGIS( line_shapefile, layer_name=os.path.splitext( os.path.basename(line_shapefile))[0], group_layer_name='DEBUG', atTop=True) else: line_shapefile = lyr_line.source() lines_desc = describe.VectorDescribe(line_shapefile) gdf_lines = lines_desc.open_geo_dataframe() epsgOut = int(self.outQgsCRS.authid().replace('EPSG:', '')) out_lines = None if self.chkSaveLinesFile.isChecked(): out_lines = self.lneSaveLinesFile.text() _ = create_points_along_line( gdf_lines, lines_desc.crs, self.dsbDistBtwnPoints.value(), self.dsbLineOffsetDist.value(), epsgOut, out_points_shapefile=self.lneSavePointsFile.text(), out_lines_shapefile=out_lines) out_lyr_points = addVectorFileToQGIS( self.lneSavePointsFile.text(), atTop=True, layer_name=os.path.splitext( os.path.basename(self.lneSavePointsFile.text()))[0]) vector_apply_unique_value_renderer(out_lyr_points, 'Strip_Name') if self.chkSaveLinesFile.isChecked(): out_lyr_lines = addVectorFileToQGIS( self.lneSaveLinesFile.text(), atTop=True, layer_name=os.path.splitext( os.path.basename(self.lneSaveLinesFile.text()))[0]) vector_apply_unique_value_renderer(out_lyr_lines, 'Strip_Name') self.cleanMessageBars(True) self.fraMain.setDisabled(False) self.iface.mainWindow().statusBar().clearMessage() self.iface.messageBar().popWidget() QtGui.qApp.restoreOverrideCursor() return super(StripTrialPointsDialog, self).accept(*args, **kwargs) except Exception as err: QtGui.qApp.restoreOverrideCursor() self.iface.mainWindow().statusBar().clearMessage() self.cleanMessageBars(True) self.fraMain.setDisabled(False) self.send_to_messagebar(str(err), level=QgsMessageBar.CRITICAL, duration=0, addToLog=True, core_QGIS=False, showLogPanel=True, exc_info=sys.exc_info()) return False # leave dialog open