class LidarProcessorDialogTest(unittest.TestCase): """Test dialog works.""" def setUp(self): """Runs before each test.""" self.dialog = LidarProcessorDialog(None) def tearDown(self): """Runs after each test.""" self.dialog = None def test_dialog_ok(self): """Test we can click OK.""" button = self.dialog.button_box.button(QDialogButtonBox.Ok) button.click() result = self.dialog.result() self.assertEqual(result, QDialog.Accepted) def test_dialog_cancel(self): """Test we can click cancel.""" button = self.dialog.button_box.button(QDialogButtonBox.Cancel) button.click() result = self.dialog.result() self.assertEqual(result, QDialog.Rejected)
def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join(self.plugin_dir, 'i18n', 'LidarProcessor_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg = LidarProcessorDialog() # Declare instance attributes self.actions = [] self.menu = self.tr(u'&LiDAR Processor') # TODO: We are going to let the user set this up in a future iteration self.toolbar = self.iface.addToolBar(u'LidarProcessor') self.toolbar.setObjectName(u'LidarProcessor') # Button Calls # Select Input Button self.dlg.inputDir.clear() self.dlg.inputDirButton.clicked.connect(self.select_input_file) # Select Output Button self.dlg.outputDir.clear() self.dlg.outputDirButton.clicked.connect(self.select_output_file) # Select Lastools Directory Button self.dlg.lastoolDir.clear() self.dlg.lastoolDirButton.clicked.connect(self.select_lastool_file) # Start Processing Button self.dlg.startProc.clicked.connect(self.proc_start) # To make the Status box uneditable by the user self.dlg.statusBox.setReadOnly(True) # Set Resolution Button for DEM FIles self.dlg.setres.clicked.connect(self.enablespin) count = 0 self.dlg.closeButton.clicked.connect(self.closeplugin)
def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value("locale/userLocale")[0:2] locale_path = os.path.join(self.plugin_dir, "i18n", "LidarProcessor_{}.qm".format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > "4.3.3": QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg = LidarProcessorDialog() # Declare instance attributes self.actions = [] self.menu = self.tr(u"&LiDAR Processor") # TODO: We are going to let the user set this up in a future iteration self.toolbar = self.iface.addToolBar(u"LidarProcessor") self.toolbar.setObjectName(u"LidarProcessor") # Button Calls # Select Input Button self.dlg.inputDir.clear() self.dlg.inputDirButton.clicked.connect(self.select_input_file) # Select Output Button self.dlg.outputDir.clear() self.dlg.outputDirButton.clicked.connect(self.select_output_file) # Select Lastools Directory Button self.dlg.lastoolDir.clear() self.dlg.lastoolDirButton.clicked.connect(self.select_lastool_file) # Start Processing Button self.dlg.startProc.clicked.connect(self.proc_start) # To make the Status box uneditable by the user self.dlg.statusBox.setReadOnly(True) # Set Resolution Button for DEM FIles self.dlg.setres.clicked.connect(self.enablespin) count = 0 self.dlg.closeButton.clicked.connect(self.closeplugin)
class LidarProcessorDialogTest(unittest.TestCase): """Test dialog works.""" def setUp(self): """Runs before each test.""" self.dialog = LidarProcessorDialog(None) def tearDown(self): """Runs after each test.""" self.dialog = None def test_dialog_ok(self): """Test we can click OK.""" button = self.dialog.button_box.button(QDialogButtonBox.Ok) button.click() result = self.dialog.result() self.assertEqual(result, QDialog.Accepted) def test_dialog_cancel(self): """Test we can click cancel.""" button = self.dialog.button_box.button(QDialogButtonBox.Cancel) button.click() result = self.dialog.result() self.assertEqual(result, QDialog.Rejected)
class LidarProcessor: """QGIS Plugin Implementation.""" # Author : Vivek Jadon and Sumeet Jain # This function is used to call corresponding functions on button click event def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join(self.plugin_dir, 'i18n', 'LidarProcessor_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg = LidarProcessorDialog() # Declare instance attributes self.actions = [] self.menu = self.tr(u'&LiDAR Processor') # TODO: We are going to let the user set this up in a future iteration self.toolbar = self.iface.addToolBar(u'LidarProcessor') self.toolbar.setObjectName(u'LidarProcessor') # Button Calls # Select Input Button self.dlg.inputDir.clear() self.dlg.inputDirButton.clicked.connect(self.select_input_file) # Select Output Button self.dlg.outputDir.clear() self.dlg.outputDirButton.clicked.connect(self.select_output_file) # Select Lastools Directory Button self.dlg.lastoolDir.clear() self.dlg.lastoolDirButton.clicked.connect(self.select_lastool_file) # Start Processing Button self.dlg.startProc.clicked.connect(self.proc_start) # To make the Status box uneditable by the user self.dlg.statusBox.setReadOnly(True) # Set Resolution Button for DEM FIles self.dlg.setres.clicked.connect(self.enablespin) count = 0 self.dlg.closeButton.clicked.connect(self.closeplugin) def closeplugin(self): self.dlg.close() qgis.utils.reloadPlugin('LidarProcessor') def enablespin(self): if self.dlg.setres.text() == "Customize Resolution": self.dlg.ncols.setEnabled(True) self.dlg.nrows.setEnabled(True) self.dlg.setres.setText("Use Default") else: self.dlg.ncols.setEnabled(False) self.dlg.nrows.setEnabled(False) self.dlg.setres.setText("Customize Resolution") # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('LidarProcessor', message) def add_action(self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): """Add a toolbar icon to the toolbar. :param icon_path: Path to the icon for this action. Can be a resource path (e.g. ':/plugins/foo/bar.png') or a normal file system path. :type icon_path: str :param text: Text that should be shown in menu items for this action. :type text: str :param callback: Function to be called when the action is triggered. :type callback: function :param enabled_flag: A flag indicating if the action should be enabled by default. Defaults to True. :type enabled_flag: bool :param add_to_menu: Flag indicating whether the action should also be added to the menu. Defaults to True. :type add_to_menu: bool :param add_to_toolbar: Flag indicating whether the action should also be added to the toolbar. Defaults to True. :type add_to_toolbar: bool :param status_tip: Optional text to show in a popup when mouse pointer hovers over the action. :type status_tip: str :param parent: Parent widget for the new action. Defaults None. :type parent: QWidget :param whats_this: Optional text to show in the status bar when the mouse pointer hovers over the action. :returns: The action that was created. Note that the action is also added to self.actions list. :rtype: QAction """ icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: self.toolbar.addAction(action) if add_to_menu: self.iface.addPluginToMenu(self.menu, action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/LidarProcessor/icon.png' self.add_action(icon_path, text=self.tr(u'LiDAR Operations'), callback=self.run, parent=self.iface.mainWindow()) def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginMenu(self.tr(u'&LiDAR Processor'), action) self.iface.removeToolBarIcon(action) # remove the toolbar del self.toolbar # Author : Vivek Jadon # Enable users to select the input Directory--- def select_input_file(self): dirname = QFileDialog.getExistingDirectory(self.dlg, "Select Input Directory", "") self.dlg.inputDir.setText(dirname) count = 0 while (count == 0): for file in os.listdir(dirname): if file.endswith(".las"): count += 1 self.dlg.inputDir.setText(dirname) if count == 0: ctypes.windll.user32.MessageBoxA( 0, "There is no las file in the selected input directory. \nPlease select another input directory", "Error!", 0) dirname = QFileDialog.getExistingDirectory( self.dlg, "Select Input Directory", "") self.listalllasfiles() # Author : Vivek Jadon # Enable users to select the input Directory--- def select_output_file(self): dirname = QFileDialog.getExistingDirectory(self.dlg, "Select Output Directory", "") self.dlg.outputDir.setText(dirname) # Author : Sumeet Jain # Enable users to select the input Directory--- def select_lastool_file(self): dirname = QFileDialog.getExistingDirectory( self.dlg, "Select the directory in which Lastools are stored", "") self.dlg.lastoolDir.setText(dirname) # Author : Sumeet Jain # List all files in the listoffiles combobox def listalllasfiles(self): nameofdir = self.dlg.inputDir.text() filearr = [] self.dlg.listoffiles.clear() for file in os.listdir(nameofdir): if file.endswith(".las"): filearr.append(file) self.dlg.listoffiles.addItems(filearr) # Author : Sumeet Jain # This func is called when Start Processing Button is pressed. It is used to perform the selected lidar operations def proc_start(self): dirname = self.dlg.lastoolDir.text() if self.dlg.inputDir.text() == "": self.iface.messageBar().pushMessage( "Error", "Please select a Input Directory ", level=QgsMessageBar.CRITICAL) elif self.dlg.outputDir.text() == "": self.iface.messageBar().pushMessage( "Error", "Please select a Output Directory ", level=QgsMessageBar.CRITICAL) elif self.dlg.lastoolDir.text() == "": self.iface.messageBar().pushMessage( "Error", "Please select a Lastool Directory ", level=QgsMessageBar.CRITICAL) else: if self.dlg.compress.isChecked(): os.chdir(dirname) if not (os.path.isfile("laszip.exe")): ctypes.windll.user32.MessageBoxA( 0, "No laszip.exe in the selected lastools directory \nPlease select a valid directory. \nHint: Select the folder path till /bin", "Error!", 0) else: self.lascompress() if self.dlg.visualize.isChecked(): os.chdir(dirname) if not (os.path.isfile("lasview.exe")): ctypes.windll.user32.MessageBoxA( 0, "No lasview.exe in the selected lastools directory \nPlease select a valid directory. \nHint: Select the folder path till /bin", "Error!", 0) else: self.lasview() if self.dlg.demGen.isChecked(): os.chdir(dirname) if not (os.path.isfile("las2dem.exe")): ctypes.windll.user32.MessageBoxA( 0, "No las2dem.exe in the selected lastools directory \nPlease select a valid directory. \nHint: Select the folder path till /bin", "Error!", 0) else: self.las2dem() if self.dlg.shpGen.isChecked(): self.tif2shp() if self.dlg.loadLayer.isChecked(): self.loadlayer() # Author : Vivek Jadon # This is performed if COMPRESS checkbox is checked. It is reponsible for Compression of Lidar Files def lascompress(self): count = 0 self.dlg.statusBox.appendPlainText("COMPRESSION") nameofinputdir = self.dlg.inputDir.text() nameofoutputdir = self.dlg.outputDir.text() nameoflastoolsdir = self.dlg.lastoolDir.text() if self.dlg.selectedFile.isChecked(): fname = str(self.dlg.listoffiles.currentText()) command = 'laszip.exe -i' + ' "' + nameofinputdir + "\\" + fname + '" -odir "' + nameofoutputdir + '" -olaz' os.chdir(nameoflastoolsdir) output1 = subprocess.check_output(command, shell=True) compratio = self.compressratio(nameofinputdir, nameofoutputdir, fname) self.dlg.statusBox.appendPlainText('Compressed ' + fname + '\n with Compression Ratio = ' + str(compratio)) count = 1 else: name = [] name = self.readfileforzip() os.chdir(nameoflastoolsdir) for k in name: output1 = subprocess.check_output(k, shell=True) count = count + 1 self.displayoutput() output2 = "Compression process complete for " + str( count) + " files. \n" self.dlg.statusBox.appendPlainText(output2) # Author : Sumeet Jain # This function updates status after completion of Compression process def displayoutput(self): nameofinputdir = self.dlg.inputDir.text() nameofoutputdir = self.dlg.outputDir.text() nameoffile = [ self.dlg.listoffiles.itemText(i) for i in range(self.dlg.listoffiles.count()) ] for i in nameoffile: compratio = self.compressratio(nameofinputdir, nameofoutputdir, i) self.dlg.statusBox.appendPlainText('Compressed ' + i + ' with Compression Ratio = ' + str(compratio)) # Author : Vivek Jadon # This function prepares compression commands def readfileforzip(self): nameofinputdir = self.dlg.inputDir.text() nameofoutputdir = self.dlg.outputDir.text() filecmd = [] nameoffile = [ self.dlg.listoffiles.itemText(i) for i in range(self.dlg.listoffiles.count()) ] for i in nameoffile: filecmd.append('laszip.exe -i' + ' "' + nameofinputdir + "\\" + i + '" -odir "' + nameofoutputdir + '" -olaz') return filecmd # Author : Sumeet Jain # This function returns the compression ratio for each file compressed def compressratio(self, ipdir, opdir, ipfilename): fnamewoext = ipfilename fnamewoext = fnamewoext[:-1] ratio = (float(os.path.getsize(ipdir + '/' + ipfilename)) / (float(os.path.getsize(opdir + '/' + fnamewoext + 'z')))) return "{:.2f}".format(ratio) # Author : Sumeet Jain # This is prefromed if VIEW checkbox is checked. It is reponsible for Visualization of Lidar Files def lasview(self): count = 0 nameofdir = self.dlg.inputDir.text() nameoflastoolsdir = self.dlg.lastoolDir.text() self.dlg.statusBox.appendPlainText("VISUALIZATION") if self.dlg.selectedFile.isChecked(): fname = str(self.dlg.listoffiles.currentText()) command = 'lasview.exe -i' + ' "' + nameofdir + "\\" + fname + '"' os.chdir(nameoflastoolsdir) output1 = subprocess.check_output(command, shell=True) self.dlg.statusBox.appendPlainText('Viewing ' + fname + '...') count = 1 else: name = [] name = self.readfileforview() os.chdir(nameoflastoolsdir) for k in name: output1 = subprocess.check_output(k, shell=True) count = count + 1 output2 = "Visualization process complete for " + str( count) + " files \n" self.dlg.statusBox.appendPlainText(output2) # Author : Vivek Jadon # This function prepares commands for visualization of LAS files def readfileforview(self): nameofdir = self.dlg.inputDir.text() filecmd = [] nameoffile = [ self.dlg.listoffiles.itemText(i) for i in range(self.dlg.listoffiles.count()) ] j = 0 for i in nameoffile: filecmd.append('lasview.exe -i' + ' "' + nameofdir + "\\" + i + '"') self.dlg.statusBox.appendPlainText('Viewing ' + i + ' ...') j = j + 1 return filecmd # Author : Vivek Jadon # This is prefromed if LAS2DEM checkbox is checked. It is reponsible for Conversion of Lidar Files to DEM files def las2dem(self): count = 0 nameofinputdir = self.dlg.inputDir.text() nameofoutputdir = self.dlg.outputDir.text() nameoflastoolsdir = self.dlg.lastoolDir.text() self.dlg.statusBox.appendPlainText("DEM GENERATION") if self.dlg.selectedFile.isChecked(): fname = str(self.dlg.listoffiles.currentText()) if self.dlg.setres.text() == "Customize Resolution": os.chdir(nameoflastoolsdir) cmdasc = 'las2dem.exe -i' + ' "' + nameofinputdir + "\\" + fname + '" -elevation -odir "' + nameofoutputdir + '" -oasc' output1 = subprocess.check_output(cmdasc, shell=True) cmdtif = 'las2dem.exe -i' + ' "' + nameofinputdir + "\\" + fname + '" -elevation -odir "' + nameofoutputdir + '" -otif' output2 = subprocess.check_output(cmdtif, shell=True) self.dlg.statusBox.appendPlainText('Generated DEM file for ' + fname + '...') else: nrows = self.dlg.nrows.text() ncols = self.dlg.ncols.text() os.chdir(nameoflastoolsdir) cmdasc = 'las2dem.exe -i' + ' "' + nameofinputdir + "\\" + fname + '" -elevation -ncols ' + str( ncols) + ' -nrows ' + str( nrows) + ' -odir "' + nameofoutputdir + '" -oasc' output1 = subprocess.check_output(cmdasc, shell=True) cmdtif = 'las2dem.exe -i' + ' "' + nameofinputdir + "\\" + fname + '" -elevation -ncols ' + str( ncols) + ' -nrows ' + str( nrows) + ' -odir "' + nameofoutputdir + '" -otif' output2 = subprocess.check_output(cmdtif, shell=True) self.dlg.statusBox.appendPlainText( 'Generated DEM file for ' + fname + ' with Dimensions \nRows: ' + str(nrows) + ' Cols: ' + str(ncols)) count = 2 else: name = [] name = self.readfilefordem() os.chdir(nameoflastoolsdir) for k in name: output1 = subprocess.check_output(k, shell=True) count = count + 1 output2 = "DEM file generation process complete for " + str( count / 2) + " files. \n" self.dlg.statusBox.appendPlainText(output2) # Author : Sumeet Jain # This function prepares commands for LAS to DEM conversion def readfilefordem(self): nameofinputdir = self.dlg.inputDir.text() nameofoutputdir = self.dlg.outputDir.text() filecmd = [] nameoffile = [ self.dlg.listoffiles.itemText(i) for i in range(self.dlg.listoffiles.count()) ] if self.dlg.setres.text() == "Customize Resolution": for i in nameoffile: filecmd.append('las2dem.exe -i' + ' "' + nameofinputdir + "\\" + i + '" -elevation -odir "' + nameofoutputdir + '" -oasc') filecmd.append('las2dem.exe -i' + ' "' + nameofinputdir + "\\" + i + '" -elevation -odir "' + nameofoutputdir + '" -otif') self.dlg.statusBox.appendPlainText('Generated DEM file for ' + i) else: j = 0 nrows = self.dlg.nrows.text() ncols = self.dlg.ncols.text() for i in nameoffile: filecmd.append('las2dem.exe -i' + ' "' + nameofinputdir + "\\" + i + '" -elevation -ncols ' + str(ncols) + ' -nrows ' + str(nrows) + ' -odir "' + nameofoutputdir + '" -oasc') filecmd.append('las2dem.exe -i' + ' "' + nameofinputdir + "\\" + i + '" -elevation -ncols ' + str(ncols) + ' -nrows ' + str(nrows) + ' -odir "' + nameofoutputdir + '" -otif') self.dlg.statusBox.appendPlainText( 'Generated DEM file for ' + i + ' with Dimensions \nRows: ' + str(nrows) + ' Cols: ' + str(ncols)) j = j + 1 return filecmd # Author : Vivek Jadon # This function prepares commands to convert TIFF files to SHP files. def tif2shp(self): count = 0 nameofinputdir = self.dlg.inputDir.text() nameofoutputdir = self.dlg.outputDir.text() self.dlg.statusBox.appendPlainText("SHP GENERATION") if self.dlg.selectedFile.isChecked(): fname = str(self.dlg.listoffiles.currentText()) fnamewoext = fname fnamewoext = fnamewoext[:-4] output1 = subprocess.check_output( ('gdaltindex ' + nameofoutputdir + "/" + fnamewoext + '.shp ' + nameofoutputdir + "/" + fnamewoext + '.tif'), shell=True) self.dlg.statusBox.appendPlainText('Generated SHP file for ' + fname + '...') count = 1 else: # name = [] # name = self.readfileforshp() # for k in name: # output1 = subprocess.check_output(k, shell=True) # count = count + 1 output1 = subprocess.check_output( ('gdaltindex ' + nameofoutputdir + "/" + 'MergedFile.shp ' + nameofoutputdir + "/" + '*.tif'), shell=True) filearr = [] for file in os.listdir(nameofoutputdir): if file.endswith(".tif"): filearr.append(file) self.dlg.statusBox.appendPlainText( 'Generated Single SHP file named "MergedFile" for') for i in filearr: self.dlg.statusBox.appendPlainText(i) count = count + 1 output2 = "SHP file generation process complete for " + str( count) + " files. \n" self.dlg.statusBox.appendPlainText(output2) # Author : Sumeet Jain # This function is used to load SHP and ASC files in Layers panel of QGIS def loadlayer(self): nameofoutputdir = self.dlg.outputDir.text() self.dlg.statusBox.appendPlainText('\nLoading shp file..') filearrshp = [] for file in os.listdir(nameofoutputdir): if file.endswith(".shp"): filearrshp.append(file) for i in filearrshp: layer = self.iface.addVectorLayer(nameofoutputdir + "/" + i, i, "ogr") self.dlg.statusBox.appendPlainText(i + ' file loaded') if not layer: output = "Layer failed to load!" self.dlg.statusBox.appendPlainText(output) def run(self): """Run method that performs all the real work""" # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: # Do something useful here - delete the line containing pass and # substitute with your code. pass
class LidarProcessor: """QGIS Plugin Implementation.""" # Author : Vivek Jadon and Sumeet Jain # This function is used to call corresponding functions on button click event def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value("locale/userLocale")[0:2] locale_path = os.path.join(self.plugin_dir, "i18n", "LidarProcessor_{}.qm".format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > "4.3.3": QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg = LidarProcessorDialog() # Declare instance attributes self.actions = [] self.menu = self.tr(u"&LiDAR Processor") # TODO: We are going to let the user set this up in a future iteration self.toolbar = self.iface.addToolBar(u"LidarProcessor") self.toolbar.setObjectName(u"LidarProcessor") # Button Calls # Select Input Button self.dlg.inputDir.clear() self.dlg.inputDirButton.clicked.connect(self.select_input_file) # Select Output Button self.dlg.outputDir.clear() self.dlg.outputDirButton.clicked.connect(self.select_output_file) # Select Lastools Directory Button self.dlg.lastoolDir.clear() self.dlg.lastoolDirButton.clicked.connect(self.select_lastool_file) # Start Processing Button self.dlg.startProc.clicked.connect(self.proc_start) # To make the Status box uneditable by the user self.dlg.statusBox.setReadOnly(True) # Set Resolution Button for DEM FIles self.dlg.setres.clicked.connect(self.enablespin) count = 0 self.dlg.closeButton.clicked.connect(self.closeplugin) def closeplugin(self): self.dlg.close() qgis.utils.reloadPlugin("LidarProcessor") def enablespin(self): if self.dlg.setres.text() == "Customize Resolution": self.dlg.ncols.setEnabled(True) self.dlg.nrows.setEnabled(True) self.dlg.setres.setText("Use Default") else: self.dlg.ncols.setEnabled(False) self.dlg.nrows.setEnabled(False) self.dlg.setres.setText("Customize Resolution") # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate("LidarProcessor", message) def add_action( self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None, ): """Add a toolbar icon to the toolbar. :param icon_path: Path to the icon for this action. Can be a resource path (e.g. ':/plugins/foo/bar.png') or a normal file system path. :type icon_path: str :param text: Text that should be shown in menu items for this action. :type text: str :param callback: Function to be called when the action is triggered. :type callback: function :param enabled_flag: A flag indicating if the action should be enabled by default. Defaults to True. :type enabled_flag: bool :param add_to_menu: Flag indicating whether the action should also be added to the menu. Defaults to True. :type add_to_menu: bool :param add_to_toolbar: Flag indicating whether the action should also be added to the toolbar. Defaults to True. :type add_to_toolbar: bool :param status_tip: Optional text to show in a popup when mouse pointer hovers over the action. :type status_tip: str :param parent: Parent widget for the new action. Defaults None. :type parent: QWidget :param whats_this: Optional text to show in the status bar when the mouse pointer hovers over the action. :returns: The action that was created. Note that the action is also added to self.actions list. :rtype: QAction """ icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: self.toolbar.addAction(action) if add_to_menu: self.iface.addPluginToMenu(self.menu, action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ":/plugins/LidarProcessor/icon.png" self.add_action(icon_path, text=self.tr(u"LiDAR Operations"), callback=self.run, parent=self.iface.mainWindow()) def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginMenu(self.tr(u"&LiDAR Processor"), action) self.iface.removeToolBarIcon(action) # remove the toolbar del self.toolbar # Author : Vivek Jadon # Enable users to select the input Directory--- def select_input_file(self): dirname = QFileDialog.getExistingDirectory(self.dlg, "Select Input Directory", "") self.dlg.inputDir.setText(dirname) count = 0 while count == 0: for file in os.listdir(dirname): if file.endswith(".las"): count += 1 self.dlg.inputDir.setText(dirname) if count == 0: ctypes.windll.user32.MessageBoxA( 0, "There is no las file in the selected input directory. \nPlease select another input directory", "Error!", 0, ) dirname = QFileDialog.getExistingDirectory(self.dlg, "Select Input Directory", "") self.listalllasfiles() # Author : Vivek Jadon # Enable users to select the input Directory--- def select_output_file(self): dirname = QFileDialog.getExistingDirectory(self.dlg, "Select Output Directory", "") self.dlg.outputDir.setText(dirname) # Author : Sumeet Jain # Enable users to select the input Directory--- def select_lastool_file(self): dirname = QFileDialog.getExistingDirectory(self.dlg, "Select the directory in which Lastools are stored", "") self.dlg.lastoolDir.setText(dirname) # Author : Sumeet Jain # List all files in the listoffiles combobox def listalllasfiles(self): nameofdir = self.dlg.inputDir.text() filearr = [] self.dlg.listoffiles.clear() for file in os.listdir(nameofdir): if file.endswith(".las"): filearr.append(file) self.dlg.listoffiles.addItems(filearr) # Author : Sumeet Jain # This func is called when Start Processing Button is pressed. It is used to perform the selected lidar operations def proc_start(self): dirname = self.dlg.lastoolDir.text() if self.dlg.inputDir.text() == "": self.iface.messageBar().pushMessage( "Error", "Please select a Input Directory ", level=QgsMessageBar.CRITICAL ) elif self.dlg.outputDir.text() == "": self.iface.messageBar().pushMessage( "Error", "Please select a Output Directory ", level=QgsMessageBar.CRITICAL ) elif self.dlg.lastoolDir.text() == "": self.iface.messageBar().pushMessage( "Error", "Please select a Lastool Directory ", level=QgsMessageBar.CRITICAL ) else: if self.dlg.compress.isChecked(): os.chdir(dirname) if not (os.path.isfile("laszip.exe")): ctypes.windll.user32.MessageBoxA( 0, "No laszip.exe in the selected lastools directory \nPlease select a valid directory. \nHint: Select the folder path till /bin", "Error!", 0, ) else: self.lascompress() if self.dlg.visualize.isChecked(): os.chdir(dirname) if not (os.path.isfile("lasview.exe")): ctypes.windll.user32.MessageBoxA( 0, "No lasview.exe in the selected lastools directory \nPlease select a valid directory. \nHint: Select the folder path till /bin", "Error!", 0, ) else: self.lasview() if self.dlg.demGen.isChecked(): os.chdir(dirname) if not (os.path.isfile("las2dem.exe")): ctypes.windll.user32.MessageBoxA( 0, "No las2dem.exe in the selected lastools directory \nPlease select a valid directory. \nHint: Select the folder path till /bin", "Error!", 0, ) else: self.las2dem() if self.dlg.shpGen.isChecked(): self.tif2shp() if self.dlg.loadLayer.isChecked(): self.loadlayer() # Author : Vivek Jadon # This is performed if COMPRESS checkbox is checked. It is reponsible for Compression of Lidar Files def lascompress(self): count = 0 self.dlg.statusBox.appendPlainText("COMPRESSION") nameofinputdir = self.dlg.inputDir.text() nameofoutputdir = self.dlg.outputDir.text() nameoflastoolsdir = self.dlg.lastoolDir.text() if self.dlg.selectedFile.isChecked(): fname = str(self.dlg.listoffiles.currentText()) command = "laszip.exe -i" + ' "' + nameofinputdir + "\\" + fname + '" -odir "' + nameofoutputdir + '" -olaz' os.chdir(nameoflastoolsdir) output1 = subprocess.check_output(command, shell=True) compratio = self.compressratio(nameofinputdir, nameofoutputdir, fname) self.dlg.statusBox.appendPlainText("Compressed " + fname + "\n with Compression Ratio = " + str(compratio)) count = 1 else: name = [] name = self.readfileforzip() os.chdir(nameoflastoolsdir) for k in name: output1 = subprocess.check_output(k, shell=True) count = count + 1 self.displayoutput() output2 = "Compression process complete for " + str(count) + " files. \n" self.dlg.statusBox.appendPlainText(output2) # Author : Sumeet Jain # This function updates status after completion of Compression process def displayoutput(self): nameofinputdir = self.dlg.inputDir.text() nameofoutputdir = self.dlg.outputDir.text() nameoffile = [self.dlg.listoffiles.itemText(i) for i in range(self.dlg.listoffiles.count())] for i in nameoffile: compratio = self.compressratio(nameofinputdir, nameofoutputdir, i) self.dlg.statusBox.appendPlainText("Compressed " + i + " with Compression Ratio = " + str(compratio)) # Author : Vivek Jadon # This function prepares compression commands def readfileforzip(self): nameofinputdir = self.dlg.inputDir.text() nameofoutputdir = self.dlg.outputDir.text() filecmd = [] nameoffile = [self.dlg.listoffiles.itemText(i) for i in range(self.dlg.listoffiles.count())] for i in nameoffile: filecmd.append( "laszip.exe -i" + ' "' + nameofinputdir + "\\" + i + '" -odir "' + nameofoutputdir + '" -olaz' ) return filecmd # Author : Sumeet Jain # This function returns the compression ratio for each file compressed def compressratio(self, ipdir, opdir, ipfilename): fnamewoext = ipfilename fnamewoext = fnamewoext[:-1] ratio = float(os.path.getsize(ipdir + "/" + ipfilename)) / ( float(os.path.getsize(opdir + "/" + fnamewoext + "z")) ) return "{:.2f}".format(ratio) # Author : Sumeet Jain # This is prefromed if VIEW checkbox is checked. It is reponsible for Visualization of Lidar Files def lasview(self): count = 0 nameofdir = self.dlg.inputDir.text() nameoflastoolsdir = self.dlg.lastoolDir.text() self.dlg.statusBox.appendPlainText("VISUALIZATION") if self.dlg.selectedFile.isChecked(): fname = str(self.dlg.listoffiles.currentText()) command = "lasview.exe -i" + ' "' + nameofdir + "\\" + fname + '"' os.chdir(nameoflastoolsdir) output1 = subprocess.check_output(command, shell=True) self.dlg.statusBox.appendPlainText("Viewing " + fname + "...") count = 1 else: name = [] name = self.readfileforview() os.chdir(nameoflastoolsdir) for k in name: output1 = subprocess.check_output(k, shell=True) count = count + 1 output2 = "Visualization process complete for " + str(count) + " files \n" self.dlg.statusBox.appendPlainText(output2) # Author : Vivek Jadon # This function prepares commands for visualization of LAS files def readfileforview(self): nameofdir = self.dlg.inputDir.text() filecmd = [] nameoffile = [self.dlg.listoffiles.itemText(i) for i in range(self.dlg.listoffiles.count())] j = 0 for i in nameoffile: filecmd.append("lasview.exe -i" + ' "' + nameofdir + "\\" + i + '"') self.dlg.statusBox.appendPlainText("Viewing " + i + " ...") j = j + 1 return filecmd # Author : Vivek Jadon # This is prefromed if LAS2DEM checkbox is checked. It is reponsible for Conversion of Lidar Files to DEM files def las2dem(self): count = 0 nameofinputdir = self.dlg.inputDir.text() nameofoutputdir = self.dlg.outputDir.text() nameoflastoolsdir = self.dlg.lastoolDir.text() self.dlg.statusBox.appendPlainText("DEM GENERATION") if self.dlg.selectedFile.isChecked(): fname = str(self.dlg.listoffiles.currentText()) if self.dlg.setres.text() == "Customize Resolution": os.chdir(nameoflastoolsdir) cmdasc = ( "las2dem.exe -i" + ' "' + nameofinputdir + "\\" + fname + '" -elevation -odir "' + nameofoutputdir + '" -oasc' ) output1 = subprocess.check_output(cmdasc, shell=True) cmdtif = ( "las2dem.exe -i" + ' "' + nameofinputdir + "\\" + fname + '" -elevation -odir "' + nameofoutputdir + '" -otif' ) output2 = subprocess.check_output(cmdtif, shell=True) self.dlg.statusBox.appendPlainText("Generated DEM file for " + fname + "...") else: nrows = self.dlg.nrows.text() ncols = self.dlg.ncols.text() os.chdir(nameoflastoolsdir) cmdasc = ( "las2dem.exe -i" + ' "' + nameofinputdir + "\\" + fname + '" -elevation -ncols ' + str(ncols) + " -nrows " + str(nrows) + ' -odir "' + nameofoutputdir + '" -oasc' ) output1 = subprocess.check_output(cmdasc, shell=True) cmdtif = ( "las2dem.exe -i" + ' "' + nameofinputdir + "\\" + fname + '" -elevation -ncols ' + str(ncols) + " -nrows " + str(nrows) + ' -odir "' + nameofoutputdir + '" -otif' ) output2 = subprocess.check_output(cmdtif, shell=True) self.dlg.statusBox.appendPlainText( "Generated DEM file for " + fname + " with Dimensions \nRows: " + str(nrows) + " Cols: " + str(ncols) ) count = 2 else: name = [] name = self.readfilefordem() os.chdir(nameoflastoolsdir) for k in name: output1 = subprocess.check_output(k, shell=True) count = count + 1 output2 = "DEM file generation process complete for " + str(count / 2) + " files. \n" self.dlg.statusBox.appendPlainText(output2) # Author : Sumeet Jain # This function prepares commands for LAS to DEM conversion def readfilefordem(self): nameofinputdir = self.dlg.inputDir.text() nameofoutputdir = self.dlg.outputDir.text() filecmd = [] nameoffile = [self.dlg.listoffiles.itemText(i) for i in range(self.dlg.listoffiles.count())] if self.dlg.setres.text() == "Customize Resolution": for i in nameoffile: filecmd.append( "las2dem.exe -i" + ' "' + nameofinputdir + "\\" + i + '" -elevation -odir "' + nameofoutputdir + '" -oasc' ) filecmd.append( "las2dem.exe -i" + ' "' + nameofinputdir + "\\" + i + '" -elevation -odir "' + nameofoutputdir + '" -otif' ) self.dlg.statusBox.appendPlainText("Generated DEM file for " + i) else: j = 0 nrows = self.dlg.nrows.text() ncols = self.dlg.ncols.text() for i in nameoffile: filecmd.append( "las2dem.exe -i" + ' "' + nameofinputdir + "\\" + i + '" -elevation -ncols ' + str(ncols) + " -nrows " + str(nrows) + ' -odir "' + nameofoutputdir + '" -oasc' ) filecmd.append( "las2dem.exe -i" + ' "' + nameofinputdir + "\\" + i + '" -elevation -ncols ' + str(ncols) + " -nrows " + str(nrows) + ' -odir "' + nameofoutputdir + '" -otif' ) self.dlg.statusBox.appendPlainText( "Generated DEM file for " + i + " with Dimensions \nRows: " + str(nrows) + " Cols: " + str(ncols) ) j = j + 1 return filecmd # Author : Vivek Jadon # This function prepares commands to convert TIFF files to SHP files. def tif2shp(self): count = 0 nameofinputdir = self.dlg.inputDir.text() nameofoutputdir = self.dlg.outputDir.text() self.dlg.statusBox.appendPlainText("SHP GENERATION") if self.dlg.selectedFile.isChecked(): fname = str(self.dlg.listoffiles.currentText()) fnamewoext = fname fnamewoext = fnamewoext[:-4] output1 = subprocess.check_output( ( "gdaltindex " + nameofoutputdir + "/" + fnamewoext + ".shp " + nameofoutputdir + "/" + fnamewoext + ".tif" ), shell=True, ) self.dlg.statusBox.appendPlainText("Generated SHP file for " + fname + "...") count = 1 else: # name = [] # name = self.readfileforshp() # for k in name: # output1 = subprocess.check_output(k, shell=True) # count = count + 1 output1 = subprocess.check_output( ("gdaltindex " + nameofoutputdir + "/" + "MergedFile.shp " + nameofoutputdir + "/" + "*.tif"), shell=True, ) filearr = [] for file in os.listdir(nameofoutputdir): if file.endswith(".tif"): filearr.append(file) self.dlg.statusBox.appendPlainText('Generated Single SHP file named "MergedFile" for') for i in filearr: self.dlg.statusBox.appendPlainText(i) count = count + 1 output2 = "SHP file generation process complete for " + str(count) + " files. \n" self.dlg.statusBox.appendPlainText(output2) # Author : Sumeet Jain # This function is used to load SHP and ASC files in Layers panel of QGIS def loadlayer(self): nameofoutputdir = self.dlg.outputDir.text() self.dlg.statusBox.appendPlainText("\nLoading shp file..") filearrshp = [] for file in os.listdir(nameofoutputdir): if file.endswith(".shp"): filearrshp.append(file) for i in filearrshp: layer = self.iface.addVectorLayer(nameofoutputdir + "/" + i, i, "ogr") self.dlg.statusBox.appendPlainText(i + " file loaded") if not layer: output = "Layer failed to load!" self.dlg.statusBox.appendPlainText(output) def run(self): """Run method that performs all the real work""" # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: # Do something useful here - delete the line containing pass and # substitute with your code. pass
def setUp(self): """Runs before each test.""" self.dialog = LidarProcessorDialog(None)
def setUp(self): """Runs before each test.""" self.dialog = LidarProcessorDialog(None)