コード例 #1
0
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)
コード例 #2
0
    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)
コード例 #3
0
    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)
コード例 #4
0
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)
コード例 #5
0
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
コード例 #6
0
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
コード例 #7
0
 def setUp(self):
     """Runs before each test."""
     self.dialog = LidarProcessorDialog(None)
コード例 #8
0
 def setUp(self):
     """Runs before each test."""
     self.dialog = LidarProcessorDialog(None)