From f40fb9c4d25084e069831bb17b4c9ccd7d453b58 Mon Sep 17 00:00:00 2001 From: Alexander Bruy Date: Wed, 25 Jan 2017 11:41:34 +0200 Subject: [PATCH] =?UTF-8?q?[processing]=20fixes=20and=20new=20tools=20for?= =?UTF-8?q?=20LiDAR=20processing=20courtesy=20of=20Niccol=C3=B2=20Marchi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../algs/lidar/LidarToolsAlgorithmProvider.py | 12 +- .../processing/algs/lidar/fusion/ASCII2DTM.py | 2 +- .../algs/lidar/fusion/CanopyMaxima.py | 48 ++++--- .../algs/lidar/fusion/CanopyModel.py | 34 ++++- .../processing/algs/lidar/fusion/Catalog.py | 34 ++++- .../processing/algs/lidar/fusion/ClipData.py | 12 +- .../algs/lidar/fusion/CloudMetrics.py | 15 +-- .../processing/algs/lidar/fusion/Cover.py | 32 +++-- .../processing/algs/lidar/fusion/Csv2Grid.py | 6 +- .../processing/algs/lidar/fusion/DTM2ASCII.py | 3 +- .../processing/algs/lidar/fusion/DTM2TIF.py | 3 +- .../algs/lidar/fusion/DensityMetrics.py | 97 ++++++++++++++ .../algs/lidar/fusion/FilterData.py | 5 +- .../algs/lidar/fusion/FusionUtils.py | 12 ++ .../algs/lidar/fusion/GridMetrics.py | 28 +++-- .../algs/lidar/fusion/GridSurfaceCreate.py | 31 ++--- .../algs/lidar/fusion/GridSurfaceStats.py | 105 ++++++++++++++++ .../algs/lidar/fusion/GroundFilter.py | 3 +- .../algs/lidar/fusion/ImageCreate.py | 13 +- .../algs/lidar/fusion/IntensityImage.py | 12 +- .../processing/algs/lidar/fusion/MergeDTM.py | 92 ++++++++++++++ .../processing/algs/lidar/fusion/MergeData.py | 4 +- .../algs/lidar/fusion/MergeRaster.py | 80 ++++++++++++ .../algs/lidar/fusion/PolyClipData.py | 14 ++- .../algs/lidar/fusion/ReturnDensity.py | 97 ++++++++++++++ .../processing/algs/lidar/fusion/SplitDTM.py | 71 +++++++++++ .../algs/lidar/fusion/SurfaceStats.py | 73 +++++++++++ .../algs/lidar/fusion/TinSurfaceCreate.py | 3 +- .../algs/lidar/fusion/TopoMetrics.py | 102 +++++++++++++++ .../processing/algs/lidar/fusion/TreeSeg.py | 118 ++++++++++++++++++ 30 files changed, 1074 insertions(+), 87 deletions(-) create mode 100644 python/plugins/processing/algs/lidar/fusion/DensityMetrics.py create mode 100644 python/plugins/processing/algs/lidar/fusion/GridSurfaceStats.py create mode 100644 python/plugins/processing/algs/lidar/fusion/MergeDTM.py create mode 100644 python/plugins/processing/algs/lidar/fusion/MergeRaster.py create mode 100644 python/plugins/processing/algs/lidar/fusion/ReturnDensity.py create mode 100644 python/plugins/processing/algs/lidar/fusion/SplitDTM.py create mode 100644 python/plugins/processing/algs/lidar/fusion/SurfaceStats.py create mode 100644 python/plugins/processing/algs/lidar/fusion/TopoMetrics.py create mode 100644 python/plugins/processing/algs/lidar/fusion/TreeSeg.py diff --git a/python/plugins/processing/algs/lidar/LidarToolsAlgorithmProvider.py b/python/plugins/processing/algs/lidar/LidarToolsAlgorithmProvider.py index be62e016cc5..590245da09b 100644 --- a/python/plugins/processing/algs/lidar/LidarToolsAlgorithmProvider.py +++ b/python/plugins/processing/algs/lidar/LidarToolsAlgorithmProvider.py @@ -140,6 +140,15 @@ from .fusion.FilterData import FilterData from .fusion.PolyClipData import PolyClipData from .fusion.ImageCreate import ImageCreate from .fusion.IntensityImage import IntensityImage +from .fusion.DensityMetrics import DensityMetrics +from .fusion.MergeDTM import MergeDTM +from .fusion.TopoMetrics import TopoMetrics +from .fusion.TreeSeg import TreeSeg +from .fusion.SplitDTM import SplitDTM +from .fusion.MergeRaster import MergeRaster +from .fusion.SurfaceStats import SurfaceStats +from .fusion.ReturnDensity import ReturnDensity # spellok +from .fusion.GridSurfaceStats import GridSurfaceStats from .fusion.FusionUtils import FusionUtils @@ -213,7 +222,8 @@ class LidarToolsAlgorithmProvider(AlgorithmProvider): Csv2Grid(), Cover(), FilterData(), GridMetrics(), GroundFilter(), GridSurfaceCreate(), MergeData(), TinSurfaceCreate(), PolyClipData(), DTM2TIF(), DTM2ASCII(), FirstLastReturn(), ASCII2DTM(), ImageCreate(), - IntensityImage() + IntensityImage(), DensityMetrics(), MergeDTM(), TopoMetrics(), TreeSeg(), + SplitDTM(), MergeRaster(), SurfaceStats(), ReturnDensity(), GridSurfaceStats() # spellok ] for alg in fusiontools: alg.group, alg.i18n_group = alg.trAlgorithm('Fusion') diff --git a/python/plugins/processing/algs/lidar/fusion/ASCII2DTM.py b/python/plugins/processing/algs/lidar/fusion/ASCII2DTM.py index 843cda9065f..f51b74069f3 100644 --- a/python/plugins/processing/algs/lidar/fusion/ASCII2DTM.py +++ b/python/plugins/processing/algs/lidar/fusion/ASCII2DTM.py @@ -51,7 +51,7 @@ class ASCII2DTM(FusionAlgorithm): self.name, self.i18n_name = self.trAlgorithm('ASCII to DTM') self.group, self.i18n_group = self.trAlgorithm('Conversion') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input ESRI ASCII layer'))) + self.INPUT, self.tr('Input ESRI ASCII layer'), optional=False)) self.addParameter(ParameterSelection( self.XYUNITS, self.tr('XY Units'), self.UNITS)) self.addParameter(ParameterSelection( diff --git a/python/plugins/processing/algs/lidar/fusion/CanopyMaxima.py b/python/plugins/processing/algs/lidar/fusion/CanopyMaxima.py index 1fbec8e8fe0..0657791cd52 100644 --- a/python/plugins/processing/algs/lidar/fusion/CanopyMaxima.py +++ b/python/plugins/processing/algs/lidar/fusion/CanopyMaxima.py @@ -32,7 +32,7 @@ import os from processing.core.parameters import ParameterFile from processing.core.parameters import ParameterNumber from processing.core.parameters import ParameterBoolean -from processing.core.outputs import OutputTable +from processing.core.outputs import OutputFile from .FusionUtils import FusionUtils from .FusionAlgorithm import FusionAlgorithm @@ -46,43 +46,53 @@ class CanopyMaxima(FusionAlgorithm): SUMMARY = 'SUMMARY' PARAM_A = 'PARAM_A' PARAM_C = 'PARAM_C' + SHAPE = 'SHAPE' def defineCharacteristics(self): self.name, self.i18n_name = self.trAlgorithm('Canopy Maxima') self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input FUSION canopy height model'))) + self.INPUT, self.tr('Input PLANS DTM canopy height model'), + optional=False)) self.addParameter(ParameterFile( - self.GROUND, self.tr('Input ground .dtm layer [optional]'))) + self.GROUND, self.tr('Input ground PLANS DTM layer [optional]'))) self.addParameter(ParameterNumber( - self.THRESHOLD, self.tr('Height threshold'), 0, None, 10.0)) - # begin + self.THRESHOLD, self.tr('Limit analysis to areas above this height threshold'), 0, None, 10.0)) + self.addParameter(ParameterNumber( self.PARAM_A, self.tr('Variable window size: parameter A'), 0, None, 2.51503)) self.addParameter(ParameterNumber( self.PARAM_C, self.tr('Parameter C'), 0, None, 0.00901)) - self.addParameter(ParameterBoolean( - self.SUMMARY, self.tr('Summary (tree height summary statistics)'), False)) - # end - self.addOutput(OutputTable( - self.OUTPUT, self.tr('Output file with maxima'))) + summary = ParameterBoolean( + self.SUMMARY, self.tr('Tree height summary statistics'), False) + summary.isAdvanced = True + self.addParameter(summary) + shape = ParameterBoolean( + self.SHAPE, self.tr('Create output shapefiles'), False) + shape.isAdvanced = True + self.addParameter(shape) + + self.addOutput(OutputFile( + self.OUTPUT, self.tr('Output file with maxima'), 'csv')) + self.addAdvancedModifiers() def processAlgorithm(self, feedback): commands = [os.path.join(FusionUtils.FusionPath(), 'CanopyMaxima.exe')] commands.append('/verbose') - ### begin - commands.append('/wse:' + str(self.getParameterValue(self.PARAM_A)) + ',0,' + str(self.getParameterValue(self.PARAM_C)) + ',0') + commands.append('/wse:' + unicode(self.getParameterValue(self.PARAM_A)) + ',0,' + unicode(self.getParameterValue(self.PARAM_C)) + ',0') + ground = self.getParameterValue(self.GROUND) + if ground: + gfiles = self.getParameterValue(self.GROUND).split(';') + if len(gfiles) == 1: + commands.append('/ground:' + str(ground)) + else: + FusionUtils.createGroundList(gfiles) + commands.append('/ground:' + str(FusionUtils.tempGroundListFilepath())) + commands.append('/threshold:' + str(self.getParameterValue(self.THRESHOLD))) if self.getParameterValue(self.SUMMARY): commands.append('/summary') - ### end self.addAdvancedModifiersToCommand(commands) - ground = self.getParameterValue(self.GROUND) - ## here it's necessary to have the support for multiple files like for INPUT. - if str(ground).strip(): - commands.append('/ground:' + str(ground)) - commands.append('/threshold:' - + str(self.getParameterValue(self.THRESHOLD))) files = self.getParameterValue(self.INPUT).split(';') if len(files) == 1: commands.append(self.getParameterValue(self.INPUT)) diff --git a/python/plugins/processing/algs/lidar/fusion/CanopyModel.py b/python/plugins/processing/algs/lidar/fusion/CanopyModel.py index d8e7c14a3b0..cdec4d9d9c1 100644 --- a/python/plugins/processing/algs/lidar/fusion/CanopyModel.py +++ b/python/plugins/processing/algs/lidar/fusion/CanopyModel.py @@ -45,6 +45,7 @@ class CanopyModel(FusionAlgorithm): INPUT = 'INPUT' OUTPUT_DTM = 'OUTPUT_DTM' + ASPECT = 'ASPECT' CELLSIZE = 'CELLSIZE' XYUNITS = 'XYUNITS' ZUNITS = 'ZUNITS' @@ -54,13 +55,15 @@ class CanopyModel(FusionAlgorithm): SMOOTH = 'SMOOTH' SLOPE = 'SLOPE' CLASS = 'CLASS' + RETURN = 'RETURN' ASCII = 'ASCII' def defineCharacteristics(self): self.name, self.i18n_name = self.trAlgorithm('Canopy Model') self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input LAS layer'))) + self.INPUT, self.tr('Input LAS layer'), + optional=False)) self.addParameter(ParameterNumber( self.CELLSIZE, self.tr('Cell Size'), 0, None, 10.0)) self.addParameter(ParameterSelection( @@ -70,7 +73,7 @@ class CanopyModel(FusionAlgorithm): self.addOutput(OutputFile( self.OUTPUT_DTM, self.tr('.dtm output surface'), 'dtm')) ground = ParameterFile( - self.GROUND, self.tr('Input ground DTM layer'), False, True) + self.GROUND, self.tr('Input ground PLANS DTM layer'), False, True) ground.isAdvanced = True self.addParameter(ground) median = ParameterString( @@ -82,13 +85,21 @@ class CanopyModel(FusionAlgorithm): smooth.isAdvanced = True self.addParameter(smooth) class_var = ParameterString( - self.CLASS, self.tr('Class'), '', False, True) + self.CLASS, self.tr('Select specific class'), '', False, True) class_var.isAdvanced = True self.addParameter(class_var) + ret_num = ParameterString( + self.RETURN, self.tr('Select specific return'), '', False, True) + ret_num.isAdvanced = True + self.addParameter(ret_num) slope = ParameterBoolean( self.SLOPE, self.tr('Calculate slope'), False) slope.isAdvanced = True self.addParameter(slope) + aspec = ParameterBoolean( + self.ASPECT, self.tr('Calculate aspect'), False) + aspec.isAdvanced = True + self.addParameter(aspect) self.addParameter(ParameterBoolean( self.ASCII, self.tr('Add an ASCII output'), False)) self.addAdvancedModifiers() @@ -98,7 +109,12 @@ class CanopyModel(FusionAlgorithm): commands.append('/verbose') ground = self.getParameterValue(self.GROUND) if str(ground).strip(): - commands.append('/ground:' + str(ground)) + gfiles = self.getParameterValue(self.GROUND).split(';') + if len(gfiles) == 1: + commands.append('/ground:' + str(ground)) + else: + FusionUtils.createGroundList(gfiles) + commands.append('/ground:' + str(FusionUtils.tempGroundListFilepath())) median = self.getParameterValue(self.MEDIAN) if str(median).strip(): commands.append('/median:' + str(median)) @@ -108,11 +124,17 @@ class CanopyModel(FusionAlgorithm): slope = self.getParameterValue(self.SLOPE) if slope: commands.append('/slope') + aspect = self.getParameterValue(self.ASPECT) + if aspect: + commands.append('/aspect') class_var = self.getParameterValue(self.CLASS) if str(class_var).strip(): commands.append('/class:' + str(class_var)) - ascii = self.getParameterValue(self.ASCII) - if ascii: + ret_num = self.getParameterValue(self.RETURN) + if str(ret_num).strip(): + commands.append('/return:' + str(ret_num)) + use_ascii = self.getParameterValue(self.ASCII) + if use_ascii: commands.append('/ascii') self.addAdvancedModifiersToCommand(commands) commands.append(self.getOutputValue(self.OUTPUT_DTM)) diff --git a/python/plugins/processing/algs/lidar/fusion/Catalog.py b/python/plugins/processing/algs/lidar/fusion/Catalog.py index 5a147a47022..512da8ca679 100644 --- a/python/plugins/processing/algs/lidar/fusion/Catalog.py +++ b/python/plugins/processing/algs/lidar/fusion/Catalog.py @@ -29,6 +29,7 @@ __revision__ = '$Format:%H$' import os from processing.core.parameters import ParameterFile from processing.core.parameters import ParameterString +from processing.core.parameters import ParameterBoolean from processing.core.outputs import OutputFile from .FusionUtils import FusionUtils from .FusionAlgorithm import FusionAlgorithm @@ -41,13 +42,19 @@ class Catalog(FusionAlgorithm): DENSITY = 'DENSITY' FIRSTDENSITY = 'FIRSTDENSITY' INTENSITY = 'INTENSITY' + INDEX = 'INDEX' + IMAGE = 'IMAGE' + DRAWTILES = 'DRAWTILES' + COVERAGE = 'COVERAGE' + CRETURNS = 'CRETURNS' ADVANCED_MODIFIERS = 'ADVANCED_MODIFIERS' def defineCharacteristics(self): self.name, self.i18n_name = self.trAlgorithm('Catalog') self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input LAS layer'))) + self.INPUT, self.tr('Input LAS layer'), + optional=False)) self.addOutput(OutputFile(self.OUTPUT, self.tr('Output files'))) density = ParameterString( self.DENSITY, @@ -67,6 +74,16 @@ class Catalog(FusionAlgorithm): '', False, True) intensity.isAdvanced = True self.addParameter(intensity) + self.addParameter(ParameterBoolean(self.INDEX, + self.tr('Create LIDAR data file indexes'), False)) + self.addParameter(ParameterBoolean(self.IMAGE, + self.tr('Create image files showing the coverage area for each LIDAR file'), False)) + self.addParameter(ParameterBoolean(self.DRAWTILES, + self.tr('Draw data file extents and names on the intensity image'), False)) + self.addParameter(ParameterBoolean(self.COVERAGE, + self.tr('Create one image that shows the nominal coverage area'), False)) + self.addParameter(ParameterBoolean(self.CRETURNS, + self.tr('Adds count return columns in the CSV and HTML output'), False)) advanced_modifiers = ParameterString( self.ADVANCED_MODIFIERS, self.tr('Additional modifiers'), '', False, True) @@ -85,6 +102,21 @@ class Catalog(FusionAlgorithm): firstdensity = self.getParameterValue(self.FIRSTDENSITY) if str(firstdensity).strip(): commands.append('/firstdensity:' + str(firstdensity)) + index = self.getParameterValue(self.INDEX) + if str(index).strip(): + commands.append('/index') + drawtiles = self.getParameterValue(self.IMAGE) + if str(drawtiles).strip(): + commands.append('/drawtiles') + coverage = self.getParameterValue(self.DRAWTILES) + if str(coverage).strip(): + commands.append('/coverage') + image = self.getParameterValue(self.COVERAGE) + if str(image).strip(): + commands.append('/image') + creturns = self.getParameterValue(self.COVERAGE) + if str(creturns).strip(): + commands.append('/countreturns') advanced_modifiers = str(self.getParameterValue(self.ADVANCED_MODIFIERS)).strip() if advanced_modifiers: commands.append(advanced_modifiers) diff --git a/python/plugins/processing/algs/lidar/fusion/ClipData.py b/python/plugins/processing/algs/lidar/fusion/ClipData.py index 6ec6d780c1e..57e498646b9 100644 --- a/python/plugins/processing/algs/lidar/fusion/ClipData.py +++ b/python/plugins/processing/algs/lidar/fusion/ClipData.py @@ -51,10 +51,11 @@ class ClipData(FusionAlgorithm): self.name, self.i18n_name = self.trAlgorithm('Clip Data') self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input LAS layer'))) + self.INPUT, self.tr('Input LAS layer'), + optional=False)) self.addParameter(ParameterExtent(self.EXTENT, self.tr('Extent'), optional=False)) self.addParameter(ParameterSelection( - self.SHAPE, self.tr('Shape'), ['Rectangle', 'Circle'])) + self.SHAPE, self.tr('Shape of the sample area'), ['Rectangle', 'Circle'])) self.addOutput(OutputFile( self.OUTPUT, self.tr('Output clipped LAS file'))) dtm = ParameterFile( @@ -74,7 +75,12 @@ class ClipData(FusionAlgorithm): commands.append('/shape:' + str(self.getParameterValue(self.SHAPE))) dtm = self.getParameterValue(self.DTM) if dtm: - commands.append('/dtm:' + str(dtm)) + gfiles = self.getParameterValue(self.DTM).split(';') + if len(gfiles) == 1: + commands.append('/ground:' + str(dtm)) + else: + FusionUtils.createGroundList(gfiles) + commands.append('/ground:' + str(FusionUtils.tempGroundListFilepath())) height = self.getParameterValue(self.HEIGHT) if height: commands.append('/height') diff --git a/python/plugins/processing/algs/lidar/fusion/CloudMetrics.py b/python/plugins/processing/algs/lidar/fusion/CloudMetrics.py index 80dbda58ad4..968baca9e40 100644 --- a/python/plugins/processing/algs/lidar/fusion/CloudMetrics.py +++ b/python/plugins/processing/algs/lidar/fusion/CloudMetrics.py @@ -32,11 +32,11 @@ __revision__ = '$Format:%H$' import os from processing.core.parameters import ParameterFile +from processing.core.parameters import ParameterNumber +from processing.core.parameters import ParameterBoolean from processing.core.outputs import OutputFile from .FusionUtils import FusionUtils from .FusionAlgorithm import FusionAlgorithm -from processing.core.parameters import ParameterString -from processing.core.parameters import ParameterBoolean class CloudMetrics(FusionAlgorithm): @@ -52,10 +52,11 @@ class CloudMetrics(FusionAlgorithm): self.name, self.i18n_name = self.trAlgorithm('Cloud Metrics') self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input LAS layer'))) + self.INPUT, self.tr('Input LAS layer'), + optional=False)) self.addOutput(OutputFile( self.OUTPUT, self.tr('Output file with tabular metric information'), 'csv')) - above = ParameterString(self.ABOVE, self.tr('Above'), '', False) + above = ParameterNumber(self.ABOVE, self.tr('Compute cover statistics above the following heightbreak:'), 0, None, 0.0) above.isAdvanced = True self.addParameter(above) firstImpulse = ParameterBoolean( @@ -66,7 +67,7 @@ class CloudMetrics(FusionAlgorithm): self.FIRSTRETURN, self.tr('First Return'), False) firstReturn.isAdvanced = True self.addParameter(firstReturn) - htmin = ParameterString(self.HTMIN, self.tr('Htmin'), '', False, True) + htmin = ParameterNumber(self.HTMIN, self.tr('Use only returns above this minimum height:'), 0, None, 0) htmin.isAdvanced = True self.addParameter(htmin) @@ -74,7 +75,7 @@ class CloudMetrics(FusionAlgorithm): commands = [os.path.join(FusionUtils.FusionPath(), 'CloudMetrics.exe')] commands.append('/verbose') above = self.getParameterValue(self.ABOVE) - if str(above).strip() != '': + if above != 0.0: commands.append('/above:' + str(above)) firstImpulse = self.getParameterValue(self.FIRSTIMPULSE) if firstImpulse: @@ -83,7 +84,7 @@ class CloudMetrics(FusionAlgorithm): if firstReturn: commands.append('/firstreturn') htmin = self.getParameterValue(self.HTMIN) - if str(htmin).strip() != '': + if htmin != 0.0: commands.append('/minht:' + str(htmin)) files = self.getParameterValue(self.INPUT).split(';') if len(files) == 1: diff --git a/python/plugins/processing/algs/lidar/fusion/Cover.py b/python/plugins/processing/algs/lidar/fusion/Cover.py index 85b044938dc..31f0484c342 100644 --- a/python/plugins/processing/algs/lidar/fusion/Cover.py +++ b/python/plugins/processing/algs/lidar/fusion/Cover.py @@ -31,6 +31,7 @@ __revision__ = '$Format:%H$' import os import subprocess from processing.core.parameters import ParameterFile +from processing.core.parameters import ParameterBoolean from processing.core.parameters import ParameterNumber from processing.core.parameters import ParameterSelection from processing.core.outputs import OutputRaster @@ -45,6 +46,8 @@ class Cover(FusionAlgorithm): CELLSIZE = 'CELLSIZE' HEIGHTBREAK = 'HEIGHTREAK' GROUND = 'GROUND' + ALLRETS = 'ALLRETS' + PENETRATION = 'PENETRATION' XYUNITS = 'XYUNITS' ZUNITS = 'ZUNITS' UNITS = ['Meter', 'Feet'] @@ -53,27 +56,42 @@ class Cover(FusionAlgorithm): self.name, self.i18n_name = self.trAlgorithm('Cover') self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input LAS layer'))) + self.INPUT, self.tr('Input LAS layer'), + optional=False)) self.addParameter(ParameterFile( - self.GROUND, self.tr('Input ground DTM layer'))) + self.GROUND, self.tr('Input ground PLANS DTM layer'), + optional=False)) self.addParameter(ParameterNumber( self.CELLSIZE, self.tr('Cell Size'), 0, None, 10.0)) self.addParameter(ParameterNumber( - self.HEIGHTBREAK, self.tr('Heightbreak'), 0, None, 10.0)) + self.HEIGHTBREAK, self.tr('Heightbreak for the cover calculation (see help)'), 0, None, 10.0)) self.addParameter(ParameterSelection( self.XYUNITS, self.tr('XY Units'), self.UNITS)) self.addParameter(ParameterSelection( self.ZUNITS, self.tr('Z Units'), self.UNITS)) - self.addOutput(OutputRaster(self.OUTPUT, self.tr('Cover'))) + self.addParameter(ParameterBoolean( + self.ALLRETS, self.tr('Use all returns instead of only first'), False)) + self.addParameter(ParameterBoolean( + self.PENETRATION, self.tr('Compute the proportion of returns close to the ground surface'), False)) + self.addOutput(OutputFile(self.OUTPUT, self.tr('Cover output file'))) self.addAdvancedModifiers() def processAlgorithm(self, feedback): commands = [os.path.join(FusionUtils.FusionPath(), 'Cover.exe')] commands.append('/verbose') + allrets = self.getParameterValue(self.ALLRETS) + if str(allrets).strip() != '': + commands.append('/all') + penetration = self.getParameterValue(self.PENETRATION) + if penetration: + commands.append('/penetration') self.addAdvancedModifiersToCommand(commands) - ground = self.getParameterValue(self.GROUND) - if str(ground).strip() != '': - commands.append('/ground:' + str(ground)) + ground = self.getParameterValue(self.GROUND).split(';') + if len(ground) == 1: + commands.append(self.getParameterValue(self.GROUND)) + else: + FusionUtils.createGroundList(ground) + commands.append(FusionUtils.tempGroundListFilepath()) outFile = self.getOutputValue(self.OUTPUT) + '.dtm' commands.append(outFile) commands.append(str(self.getParameterValue(self.HEIGHTBREAK))) diff --git a/python/plugins/processing/algs/lidar/fusion/Csv2Grid.py b/python/plugins/processing/algs/lidar/fusion/Csv2Grid.py index b3965133024..b44621b1854 100644 --- a/python/plugins/processing/algs/lidar/fusion/Csv2Grid.py +++ b/python/plugins/processing/algs/lidar/fusion/Csv2Grid.py @@ -27,7 +27,7 @@ __revision__ = '$Format:%H$' import os from processing.core.parameters import ParameterFile -from processing.core.parameters import ParameterString +from processing.core.parameters import ParameterNumber from processing.core.outputs import OutputFile from .FusionAlgorithm import FusionAlgorithm from .FusionUtils import FusionUtils @@ -42,8 +42,8 @@ class Csv2Grid(FusionAlgorithm): def defineCharacteristics(self): self.name, self.i18n_name = self.trAlgorithm('Csv2Grid') self.group, self.i18n_group = self.trAlgorithm('Points') - self.addParameter(ParameterFile(self.INPUT, self.tr('CSV Files'))) - self.addParameter(ParameterString(self.COLUMN, self.tr('Column'))) + self.addParameter(ParameterFile(self.INPUT, self.tr('CSV Files'), optional=False)) + self.addParameter(ParameterNumber(self.COLUMN, self.tr('Column'), 0, None, 0z)) self.addOutput(OutputFile(self.OUTPUT, self.tr('Raster Output file'), 'asc')) def processAlgorithm(self, feedback): diff --git a/python/plugins/processing/algs/lidar/fusion/DTM2ASCII.py b/python/plugins/processing/algs/lidar/fusion/DTM2ASCII.py index e562ba26953..bd7dadd602e 100644 --- a/python/plugins/processing/algs/lidar/fusion/DTM2ASCII.py +++ b/python/plugins/processing/algs/lidar/fusion/DTM2ASCII.py @@ -43,7 +43,8 @@ class DTM2ASCII(FusionAlgorithm): self.name, self.i18n_name = self.trAlgorithm('DTM to ASCII') self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input canopy surface (.dtm)'))) + self.INPUT, self.tr('Input canopy surface (.dtm)'), + optional=False)) self.addParameter(ParameterSelection( self.SWITCH, self.tr('Output format'), ['raster (ASCII)', 'csv'])) diff --git a/python/plugins/processing/algs/lidar/fusion/DTM2TIF.py b/python/plugins/processing/algs/lidar/fusion/DTM2TIF.py index 113f1421f13..b816aa4315d 100644 --- a/python/plugins/processing/algs/lidar/fusion/DTM2TIF.py +++ b/python/plugins/processing/algs/lidar/fusion/DTM2TIF.py @@ -44,7 +44,8 @@ class DTM2TIF(FusionAlgorithm): self.name, self.i18n_name = self.trAlgorithm('DTM to TIF') self.group, self.i18n_group = self.trAlgorithm('Conversion') self.addParameter(ParameterFile( - self.INPUT, self.tr("Input .dtm layer"))) + self.INPUT, self.tr("Input .dtm layer"), + optional=False)) self.addOutput(OutputRaster(self.OUTPUT, self.tr('Output file name'))) self.addAdvancedModifiers() diff --git a/python/plugins/processing/algs/lidar/fusion/DensityMetrics.py b/python/plugins/processing/algs/lidar/fusion/DensityMetrics.py new file mode 100644 index 00000000000..3920bf29efe --- /dev/null +++ b/python/plugins/processing/algs/lidar/fusion/DensityMetrics.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + DensityMetrics.py + --------------------- + Date : August 2016 + Copyright : (C) 2016 by Niccolo' Marchi + Email : sciurusurbanus at hotmail dot it +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = "Niccolo' Marchi" +__date__ = 'August 2016' +__copyright__ = "(C) 2016 by Niccolo' Marchi" + +# This will get replaced with a git SHA1 when you do a git archive + +__revision__ = '$Format:%H$' + +import os +import subprocess +from processing.core.parameters import ParameterBoolean +from processing.core.parameters import ParameterFile +from processing.core.parameters import ParameterNumber +from processing.core.outputs import OutputFile +from .FusionAlgorithm import FusionAlgorithm +from .FusionUtils import FusionUtils + + +class DensityMetrics(FusionAlgorithm): + + INPUT = 'INPUT' + OUTPUT = 'OUTPUT' + CELLSIZE = 'CELLSIZE' + SLICE = 'SLICE' + GROUND = 'GROUND' + FIRST = 'FIRST' + NOCSV = 'NOCSV' + HTLIM = 'HTLIM' + + def defineCharacteristics(self): + self.name, self.i18n_name = self.trAlgorithm('Density Metrics') + self.group, self.i18n_group = self.trAlgorithm('Points') + self.addParameter(ParameterFile( + self.INPUT, self.tr('Input LAS layer'), optional=False)) + self.addParameter(ParameterFile( + self.GROUND, self.tr('Input ground PLANS DTM layer'), optional=False)) + self.addParameter(ParameterNumber( + self.CELLSIZE, self.tr('Cellsize'), 0, None, 5.0)) + self.addParameter(ParameterNumber( + self.SLICE, self.tr('Slice thickness'), 0, None, 2.0)) + self.addParameter(ParameterNumber( + self.HTLIM, self.tr('Maximum height limit'), 0, None, 50.0)) + self.addParameter(ParameterBoolean( + self.FIRST, self.tr('Use only first returns'), False)) + self.addParameter(ParameterBoolean( + self.NOCSV, self.tr('Do not create a CSV output file for cell metrics'), False)) + self.addOutput(OutputFile( + self.OUTPUT, self.tr('Base name for output files'))) + self.addAdvancedModifiers() + + def processAlgorithm(self, progress): + commands = [os.path.join(FusionUtils.FusionPath(), 'DensityMetrics.exe')] + commands.append('/verbose') + first = self.getParameterValue(self.FIRST) + if first: + commands.append('/first') + nocsv = self.getParameterValue(self.NOCSV) + if nocsv: + commands.append('/nocsv') + commands.append('/maxsliceht:' + unicode(self.getParameterValue(self.HTLIM))) + self.addAdvancedModifiersToCommand(commands) + ground = self.getParameterValue(self.GROUND).split(';') + if len(ground) == 1: + commands.append(self.getParameterValue(self.GROUND)) + else: + FusionUtils.createGroundList(ground) + commands.append(FusionUtils.tempGroundListFilepath()) + commands.append(unicode(self.getParameterValue(self.CELLSIZE))) + commands.append(unicode(self.getParameterValue(self.SLICE))) + outFile = self.getOutputValue(self.OUTPUT) + commands.append(outFile) + files = self.getParameterValue(self.INPUT).split(';') + if len(files) == 1: + commands.append(self.getParameterValue(self.INPUT)) + else: + FusionUtils.createFileList(files) + commands.append(FusionUtils.tempFileListFilepath()) + FusionUtils.runFusion(commands, progress) diff --git a/python/plugins/processing/algs/lidar/fusion/FilterData.py b/python/plugins/processing/algs/lidar/fusion/FilterData.py index 52a7e6625ef..1d13240d717 100644 --- a/python/plugins/processing/algs/lidar/fusion/FilterData.py +++ b/python/plugins/processing/algs/lidar/fusion/FilterData.py @@ -48,7 +48,8 @@ class FilterData(FusionAlgorithm): self.name, self.i18n_name = self.trAlgorithm('Filter Data outliers') self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input LAS layer'))) + self.INPUT, self.tr('Input LAS layer'), + optional=False)) self.addParameter(ParameterNumber( self.VALUE, self.tr('Standard Deviation multiplier'))) self.addParameter(ParameterNumber( @@ -61,7 +62,7 @@ class FilterData(FusionAlgorithm): commands = [os.path.join(FusionUtils.FusionPath(), 'FilterData.exe')] commands.append('/verbose') self.addAdvancedModifiersToCommand(commands) - commands.append('/outlier') + commands.append('outlier') commands.append(str(self.getParameterValue(self.VALUE))) commands.append(str(self.getParameterValue(self.WINDOWSIZE))) outFile = self.getOutputValue(self.OUTPUT) diff --git a/python/plugins/processing/algs/lidar/fusion/FusionUtils.py b/python/plugins/processing/algs/lidar/fusion/FusionUtils.py index c67e73f8062..fd185a4f364 100644 --- a/python/plugins/processing/algs/lidar/fusion/FusionUtils.py +++ b/python/plugins/processing/algs/lidar/fusion/FusionUtils.py @@ -75,3 +75,15 @@ class FusionUtils(object): for line in iter(proc.readline, ''): loglines.append(line) ProcessingLog.addToLog(ProcessingLog.LOG_INFO, loglines) + + @staticmethod + def tempGroundListFilepath(): + filename = 'fusion_groundFiles_list.txt' + filepath = os.path.join(userFolder(), filename) + return filepath + + @staticmethod + def createGroundList(gfiles): + with open(FusionUtils.tempGroundListFilepath(), 'w') as outg: + for f in gfiles: + outg.write(f + '\n') diff --git a/python/plugins/processing/algs/lidar/fusion/GridMetrics.py b/python/plugins/processing/algs/lidar/fusion/GridMetrics.py index 43809d5f7de..531399d8f6a 100644 --- a/python/plugins/processing/algs/lidar/fusion/GridMetrics.py +++ b/python/plugins/processing/algs/lidar/fusion/GridMetrics.py @@ -52,6 +52,7 @@ class GridMetrics(FusionAlgorithm): CELLSIZE = 'CELLSIZE' OUTLIER = 'OUTLIER' FIRST = 'FIRST' + FUEL = 'FUEL' MINHT = 'MINHT' CLASS = 'CLASS' @@ -59,13 +60,19 @@ class GridMetrics(FusionAlgorithm): self.name, self.i18n_name = self.trAlgorithm('Grid Metrics') self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input LAS layer'))) + self.INPUT, self.tr('Input LAS layer'), + optional=False)) self.addParameter(ParameterFile( - self.GROUND, self.tr('Input ground DTM layer'))) + self.GROUND, self.tr('Input ground PLANS DTM layer'), + optional=False)) self.addParameter(ParameterNumber( self.HEIGHT, self.tr('Height break'))) self.addParameter(ParameterNumber( self.CELLSIZE, self.tr('Cell Size'))) + self.addParameter(ParameterBoolean( + self.FIRST, self.tr('Use only first returns'), False)) + self.addParameter(ParameterBoolean( + self.FUEL, self.tr('Apply fuel parameter models (cannot be used with /first switch)'), False)) self.addOutput(OutputFile( self.OUTPUT_CSV_ELEVATION, self.tr('Output table with grid metrics'))) @@ -89,9 +96,6 @@ class GridMetrics(FusionAlgorithm): self.OUTLIER, self.tr('Outlier:low,high'), '', False, True) outlier.isAdvanced = True self.addParameter(outlier) - first = ParameterBoolean(self.FIRST, self.tr('First'), False) - first.isAdvanced = True - self.addParameter(first) minht = ParameterString(self.MINHT, self.tr('Htmin'), '', False, True) minht.isAdvanced = True self.addParameter(minht) @@ -99,6 +103,7 @@ class GridMetrics(FusionAlgorithm): self.CLASS, self.tr('Class (set blank if not used)'), '', False, True) class_var.isAdvanced = True self.addParameter(class_var) + self.addAdvancedModifiers() def processAlgorithm(self, feedback): commands = [os.path.join(FusionUtils.FusionPath(), 'GridMetrics.exe')] @@ -109,15 +114,24 @@ class GridMetrics(FusionAlgorithm): first = self.getParameterValue(self.FIRST) if first: commands.append('/first') + fuel = self.getParameterValue(self.FUEL) + if fuel: + commands.append('/fuel') minht = self.getParameterValue(self.MINHT) if str(minht).strip() != '': commands.append('/minht:' + str(minht)) class_var = self.getParameterValue(self.CLASS) if str(class_var).strip() != '': commands.append('/class:' + str(class_var)) - commands.append(self.getParameterValue(self.GROUND)) + self.addAdvancedModifiersToCommand(commands) + ground = self.getParameterValue(self.GROUND).split(';') + if len(ground) == 1: + commands.append(self.getParameterValue(self.GROUND)) + else: + FusionUtils.createGroundList(ground) + commands.append(FusionUtils.tempGroundListFilepath()) commands.append(str(self.getParameterValue(self.HEIGHT))) - commands.append(str(self.getParameterValue(self.CELLSIZE))) + commands.append(str(self.getParameterValue(self.CELLSIZE))) commands.append(self.getOutputValue(self.OUTPUT_CSV_ELEVATION)) files = self.getParameterValue(self.INPUT).split(';') if len(files) == 1: diff --git a/python/plugins/processing/algs/lidar/fusion/GridSurfaceCreate.py b/python/plugins/processing/algs/lidar/fusion/GridSurfaceCreate.py index c027f593a83..084eed969ef 100644 --- a/python/plugins/processing/algs/lidar/fusion/GridSurfaceCreate.py +++ b/python/plugins/processing/algs/lidar/fusion/GridSurfaceCreate.py @@ -61,7 +61,8 @@ class GridSurfaceCreate(FusionAlgorithm): self.name, self.i18n_name = self.trAlgorithm('Grid Surface Create') self.group, self.i18n_group = self.trAlgorithm('Surface') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input LAS layer'))) + self.INPUT, self.tr('Input LAS layer'), + optional=False)) self.addParameter(ParameterNumber( self.CELLSIZE, self.tr('Cell Size'), 0, None, 10.0)) self.addParameter(ParameterSelection( @@ -70,28 +71,28 @@ class GridSurfaceCreate(FusionAlgorithm): self.ZUNITS, self.tr('Z Units'), self.UNITS)) self.addOutput(OutputFile( self.OUTPUT_DTM, self.tr('DTM Output Surface'), 'dtm')) - spike = ParameterString( - self.SPIKE, self.tr('Spike (set blank if not used)'), '', False, True) + spike = ParameterNumber( + self.SPIKE, self.tr('Filter final surface to remove spikes with slopes greater than # percent'), 0, None, 0.0) spike.isAdvanced = True self.addParameter(spike) - median = ParameterString( - self.MEDIAN, self.tr('Median'), '', False, True) + median = ParameterNumber( + self.MEDIAN, self.tr('Apply median filter to model using # by # neighbor window'), 0, None, 0.0) median.isAdvanced = True self.addParameter(median) - smooth = ParameterString( - self.SMOOTH, self.tr('Smooth'), '', False, True) + smooth = ParameterNumber( + self.SMOOTH, self.tr('Apply mean filter to model using # by # neighbor window'), 0, None, 0.0) smooth.isAdvanced = True self.addParameter(smooth) - slope = ParameterString( - self.SLOPE, self.tr('Slope'), '', False, True) + slope = ParameterNumber( + self.SLOPE, self.tr('Filter areas from the surface with slope greater than # percent'), 0, None, 0.0) slope.isAdvanced = True self.addParameter(slope) minimum = ParameterBoolean( - self.MINIMUM, self.tr('Minimum (set blank if not used)'), False) + self.MINIMUM, self.tr('Use the lowest point in each cell as the surface elevation'), False) minimum.isAdvanced = True self.addParameter(minimum) class_var = ParameterString( - self.CLASS, self.tr('Class(es)'), 2, False, True) + self.CLASS, self.tr('Class(es)'), '', False, True) class_var.isAdvanced = True self.addParameter(class_var) advance_modifiers = ParameterString( @@ -103,16 +104,16 @@ class GridSurfaceCreate(FusionAlgorithm): commands = [os.path.join(FusionUtils.FusionPath(), 'GridSurfaceCreate.exe')] commands.append('/verbose') spike = self.getParameterValue(self.SPIKE) - if str(spike).strip(): + if spike != 0.0: commands.append('/spike:' + str(spike)) median = self.getParameterValue(self.MEDIAN) - if str(median).strip(): + if median != 0.0: commands.append('/median:' + str(median)) smooth = self.getParameterValue(self.SMOOTH) - if str(smooth).strip(): + if smooth != 0.0: commands.append('/smooth:' + str(smooth)) slope = self.getParameterValue(self.SLOPE) - if str(slope).strip(): + if slope != 0.0: commands.append('/slope:' + str(slope)) minimum = self.getParameterValue(self.MINIMUM) if str(minimum).strip(): diff --git a/python/plugins/processing/algs/lidar/fusion/GridSurfaceStats.py b/python/plugins/processing/algs/lidar/fusion/GridSurfaceStats.py new file mode 100644 index 00000000000..a5f7b812c25 --- /dev/null +++ b/python/plugins/processing/algs/lidar/fusion/GridSurfaceStats.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + GridSurfaceStats.py + --------------------- + Date : November 2016 + Copyright : (C) 2016 by Niccolo' Marchi + Email : sciurusurbanus at hotmail dot it +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = "Niccolo' Marchi" +__date__ = 'November 2016' +__copyright__ = "(C) 2016 by Niccolo' Marchi" + +# This will get replaced with a git SHA1 when you do a git archive + +__revision__ = '$Format:%H$' + +import os +from processing.core.parameters import ParameterFile +from processing.core.parameters import ParameterNumber +from processing.core.parameters import ParameterBoolean +from processing.core.outputs import OutputFile +from .FusionAlgorithm import FusionAlgorithm +from .FusionUtils import FusionUtils + + +class GridSurfaceStats(FusionAlgorithm): + + INPUT = 'INPUT' + OUTPUT = 'OUTPUT' + SAFACT = 'SAFACT' + AREA = 'AREA' + ASCII = 'ASCII' + SVONLY = 'SVONLY' + GROUND = 'GROUND' + + def defineCharacteristics(self): + self.name, self.i18n_name = self.trAlgorithm('Grid Surface Stats') + self.group, self.i18n_group = self.trAlgorithm('Surface') + self.addParameter(ParameterFile( + self.INPUT, self.tr('Input PLANS DTM canopy height model'), optional=False)) + self.addParameter(ParameterNumber( + self.SAFACT, self.tr('Multiplier for outputfile cell size'), 0, None, 1.0)) + self.addOutput(OutputFile( + self.OUTPUT, self.tr('Output file'))) + area = ParameterBoolean( + self.AREA, self.tr('Compute the surface area of inputfile instead of the surface area divided by the flat cell area'), False) + area.isAdvanced = True + self.addParameter(area) + ascii = ParameterBoolean( + self.ASCII, self.tr('Output all files in ASCII raster format instead of PLANS DTM ones'), False) + ascii.isAdvanced = True + self.addParameter(ascii) + svonly = ParameterBoolean( + self.SVONLY, self.tr('Output only the surface volume metric layer'), False) + svonly.isAdvanced = True + self.addParameter(svonly) + + ground = ParameterFile( + self.GROUND, self.tr('Use the specified surface model to represent the ground surface'), False, True) + ground.isAdvanced = True + self.addParameter(ground) + + self.addAdvancedModifiers() + + def processAlgorithm(self, progress): + commands = [os.path.join(FusionUtils.FusionPath(), 'GridSurfaceStats.exe')] + commands.append('/verbose') + area = self.getParameterValue(self.AREA) + if area: + commands.append('/area') + ascii = self.getParameterValue(self.ASCII) + if ascii: + commands.append('/ascii') + svonly = self.getParameterValue(self.SVONLY) + if svonly: + commands.append('/svonly') + ground = self.getParameterValue(self.GROUND) + if ground: + gfiles = self.getParameterValue(self.GROUND).split(';') + if len(gfiles) == 1: + commands.append('/ground:' + unicode(ground)) + else: + FusionUtils.createGroundList(gfiles) + commands.append('/ground:' + unicode(FusionUtils.tempGroundListFilepath())) + self.addAdvancedModifiersToCommand(commands) + files = self.getParameterValue(self.INPUT).split(';') + if len(files) == 1: + commands.append(self.getParameterValue(self.INPUT)) + else: + FusionUtils.createFileList(files) + commands.append(FusionUtils.tempFileListFilepath()) + commands.append(self.getOutputValue(self.OUTPUT)) + commands.append(unicode(self.getParameterValue(self.SAFACT))) + FusionUtils.runFusion(commands, progress) diff --git a/python/plugins/processing/algs/lidar/fusion/GroundFilter.py b/python/plugins/processing/algs/lidar/fusion/GroundFilter.py index 598126bc497..db8fa6b8331 100644 --- a/python/plugins/processing/algs/lidar/fusion/GroundFilter.py +++ b/python/plugins/processing/algs/lidar/fusion/GroundFilter.py @@ -48,7 +48,8 @@ class GroundFilter(FusionAlgorithm): self.name, self.i18n_name = self.trAlgorithm('Ground Filter') self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input LAS layer'))) + self.INPUT, self.tr('Input LAS layer'), + optional=False)) self.addParameter(ParameterNumber(self.CELLSIZE, self.tr('Cell size for intermediate surfaces'), 0, None, 10)) self.addOutput(OutputFile( diff --git a/python/plugins/processing/algs/lidar/fusion/ImageCreate.py b/python/plugins/processing/algs/lidar/fusion/ImageCreate.py index 35753cf2b42..23555fdf2c2 100644 --- a/python/plugins/processing/algs/lidar/fusion/ImageCreate.py +++ b/python/plugins/processing/algs/lidar/fusion/ImageCreate.py @@ -52,7 +52,8 @@ class ImageCreate(FusionAlgorithm): self.name, self.i18n_name = self.trAlgorithm('ImageCreate') self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input LAS'))) + self.INPUT, self.tr('Input LAS'), + optional=False)) self.addParameter(ParameterSelection( self.COLOROPTION, self.tr('Method to assign color'), ['Intensity', 'Elevation', 'Height'])) @@ -72,14 +73,20 @@ class ImageCreate(FusionAlgorithm): commands.append('/verbose') commands.append('/coloroption:' + str(self.getParameterValue(self.COLOROPTION))) ground = self.getParameterValue(self.GROUND) - if str(ground).strip(): - commands.append('/dtm:' + str(ground)) + if ground: + gfiles = self.getParameterValue(self.GROUND).split(';') + if len(gfiles) == 1: + commands.append('/ground:' + str(ground)) + else: + FusionUtils.createGroundList(gfiles) + commands.append('/ground:' + str(FusionUtils.tempGroundListFilepath())) if self.getParameterValue(self.RGB): commands.append('/rgb') if self.getParameterValue(self.SWITCH) == 0: commands.append('/jpg') else: commands.append('/bmp') + self.addAdvancedModifiersToCommand(commands) outFile = self.getOutputValue(self.OUTPUT) commands.append(outFile) commands.append(str(self.getParameterValue(self.PIXEL))) diff --git a/python/plugins/processing/algs/lidar/fusion/IntensityImage.py b/python/plugins/processing/algs/lidar/fusion/IntensityImage.py index f21f4d94587..232cf67ce8b 100644 --- a/python/plugins/processing/algs/lidar/fusion/IntensityImage.py +++ b/python/plugins/processing/algs/lidar/fusion/IntensityImage.py @@ -46,6 +46,7 @@ class IntensityImage(FusionAlgorithm): HIST = 'HIST' PIXEL = 'PIXEL' SWITCH = 'SWITCH' + FALIGN = 'FALIGN' OUTPUT = 'OUTPUT' def defineCharacteristics(self): @@ -53,7 +54,8 @@ class IntensityImage(FusionAlgorithm): self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input file'))) + self.INPUT, self.tr('Input file'), + optional=False)) self.addParameter(ParameterBoolean( self.ALLRET, self.tr('Use all returns instead of only first'), False)) self.addParameter(ParameterBoolean( @@ -64,6 +66,10 @@ class IntensityImage(FusionAlgorithm): self.PIXEL, self.tr('Pixel size'), 0, None, 1.0)) self.addParameter(ParameterSelection( self.SWITCH, self.tr('Output format'), ['Bitmap', 'JPEG'])) + falign = ParameterBoolean( + self.FALIGN, self.tr('Force alignment to match other raster products'), False) + falign.isAdvanced = True + self.addParameter(falign) self.addOutput(OutputFile(self.OUTPUT, 'Output image')) self.addAdvancedModifiers() @@ -78,7 +84,9 @@ class IntensityImage(FusionAlgorithm): commands.append('/hist') if self.getParameterValue(self.SWITCH) == 1: commands.append('/jpg') - commands.append(str(self.getParameterValue(self.PIXEL))) + if self.getParameterValue(self.FALIGN): + commands.append('/rasterorigin') + commands.append(unicode(self.getParameterValue(self.PIXEL))) outFile = self.getOutputValue(self.OUTPUT) commands.append(outFile) files = self.getParameterValue(self.INPUT).split(';') diff --git a/python/plugins/processing/algs/lidar/fusion/MergeDTM.py b/python/plugins/processing/algs/lidar/fusion/MergeDTM.py new file mode 100644 index 00000000000..88f98d7de3e --- /dev/null +++ b/python/plugins/processing/algs/lidar/fusion/MergeDTM.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + MergeDTM.py + --------------------- + Date : August 2016 + Copyright : (C) 2016 by Niccolo' Marchi + Email : sciurusurbanus at hotmail dot it +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = "Niccolo' Marchi" +__date__ = 'August 2016' +__copyright__ = "(C) 2016 by Niccolo' Marchi" + +# This will get replaced with a git SHA1 when you do a git archive + +__revision__ = '$Format:%H$' + +import os +from processing.core.parameters import ParameterBoolean +from processing.core.parameters import ParameterFile +from processing.core.parameters import ParameterNumber +from processing.core.outputs import OutputFile +from .FusionAlgorithm import FusionAlgorithm +from .FusionUtils import FusionUtils + + +class MergeDTM(FusionAlgorithm): + + INPUT = 'INPUT' + OUTPUT = 'OUTPUT' + CELLSIZE = 'CELLSIZE' + EXTENT = 'EXTENT' + DISK = 'DISK' + + def defineCharacteristics(self): + self.name, self.i18n_name = self.trAlgorithm('Merge PLANS DTM files') + self.group, self.i18n_group = self.trAlgorithm('Points') + self.addParameter(ParameterFile( + self.INPUT, self.tr('Input PLANS DTM files'), optional=False)) + self.addOutput(OutputFile( + self.OUTPUT, self.tr('Output merged file'))) + + cellsize = ParameterNumber( + self.CELLSIZE, self.tr('Resample the input DTM data to the following cellsize'), 0, None, 0.0) + cellsize.isAdvanced = True + self.addParameter(cellsize) + + extent = ParameterBoolean( + self.EXTENT, self.tr('Preserve the exact extent of the input models'), False) + extent.isAdvanced = True + self.addParameter(extent) + + disk = ParameterBoolean( + self.DISK, self.tr('Merge the files to a disk file. USE ONLY IF DEFAULT METHOD FAILS'), False) + disk.isAdvanced = True + self.addParameter(disk) + + self.addAdvancedModifiers() + + def processAlgorithm(self, progress): + commands = [os.path.join(FusionUtils.FusionPath(), 'MergeDTM.exe')] + commands.append('/verbose') + + cellsize = self.getParameterValue(self.CELLSIZE) + if cellsize != 0.0: + commands.append('/cellsize:' + unicode(self.getParameterValue(self.CELLSIZE))) + extent = self.getParameterValue(self.EXTENT) + if extent: + commands.append('/exactextent') + disk = self.getParameterValue(self.DISK) + if disk: + commands.append('/disk') + self.addAdvancedModifiersToCommand(commands) + outFile = self.getOutputValue(self.OUTPUT) + commands.append(outFile) + files = self.getParameterValue(self.INPUT).split(';') + if len(files) == 1: + commands.append(self.getParameterValue(self.INPUT)) + else: + FusionUtils.createFileList(files) + commands.append(FusionUtils.tempFileListFilepath()) + FusionUtils.runFusion(commands, progress) diff --git a/python/plugins/processing/algs/lidar/fusion/MergeData.py b/python/plugins/processing/algs/lidar/fusion/MergeData.py index 6053d531ce5..294fde3fbe6 100644 --- a/python/plugins/processing/algs/lidar/fusion/MergeData.py +++ b/python/plugins/processing/algs/lidar/fusion/MergeData.py @@ -43,7 +43,9 @@ class MergeData(FusionAlgorithm): self.name, self.i18n_name = self.trAlgorithm('Merge LAS Files') self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input LAS files'))) + self.INPUT, self.tr('Input LAS files'), + optional=False)) + self.addAdvancedModifiers() self.addOutput(OutputFile( self.OUTPUT, self.tr('Output merged LAS file'))) diff --git a/python/plugins/processing/algs/lidar/fusion/MergeRaster.py b/python/plugins/processing/algs/lidar/fusion/MergeRaster.py new file mode 100644 index 00000000000..902297eb145 --- /dev/null +++ b/python/plugins/processing/algs/lidar/fusion/MergeRaster.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + MergeRaster.py + --------------------- + Date : November 2016 + Copyright : (C) 2016 by Niccolo' Marchi + Email : sciurusurbanus at hotmail dot it +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = "Niccolo' Marchi" +__date__ = 'November 2016' +__copyright__ = "(C) 2016 by Niccolo' Marchi" + +# This will get replaced with a git SHA1 when you do a git archive + +__revision__ = '$Format:%H$' + +import os +from processing.core.parameters import ParameterFile +from processing.core.parameters import ParameterBoolean +from processing.core.parameters import ParameterString +from processing.core.outputs import OutputFile +from .FusionAlgorithm import FusionAlgorithm +from .FusionUtils import FusionUtils + + +class MergeRaster(FusionAlgorithm): + + INPUT = 'INPUT' + OUTPUT = 'OUTPUT' + OVERL = 'OVERL' + COMP = 'COMP' + + def defineCharacteristics(self): + self.name, self.i18n_name = self.trAlgorithm('Merge ASCII files') + self.group, self.i18n_group = self.trAlgorithm('Points') + self.addParameter(ParameterFile( + self.INPUT, self.tr('Input ASCII files'), optional=False)) + self.addOutput(OutputFile( + self.OUTPUT, self.tr('Output file'), 'asc')) + + overl = ParameterString( + self.OVERL, self.tr('Specify how overlap areas should be treated'), '', False, True) + overl.isAdvanced = True + self.addParameter(overl) + comp = ParameterBoolean( + self.COMP, self.tr('Compare values in cells common to two or more input files'), False) + comp.isAdvanced = True + self.addParameter(comp) + self.addAdvancedModifiers() + + def processAlgorithm(self, progress): + commands = [os.path.join(FusionUtils.FusionPath(), 'MergeRaster.exe')] + commands.append('/verbose') + overl = self.getParameterValue(self.OVERL) + if overl: + commands.append('/overlap:' + unicode(overl)) + comp = self.getParameterValue(self.COMP) + if comp: + commands.append('/compare') + self.addAdvancedModifiersToCommand(commands) + outFile = self.getOutputValue(self.OUTPUT) + commands.append(outFile) + files = self.getParameterValue(self.INPUT).split(';') + if len(files) == 1: + commands.append(self.getParameterValue(self.INPUT)) + else: + FusionUtils.createFileList(files) + commands.append(FusionUtils.tempFileListFilepath()) + FusionUtils.runFusion(commands, progress) diff --git a/python/plugins/processing/algs/lidar/fusion/PolyClipData.py b/python/plugins/processing/algs/lidar/fusion/PolyClipData.py index 4ec2eb44d2f..ff6a885048e 100644 --- a/python/plugins/processing/algs/lidar/fusion/PolyClipData.py +++ b/python/plugins/processing/algs/lidar/fusion/PolyClipData.py @@ -45,21 +45,22 @@ class PolyClipData(FusionAlgorithm): MASK = 'MASK' FIELD = 'FIELD' VALUE = 'VALUE' + MULTIFILE = 'MULTIFILE' def defineCharacteristics(self): self.name, self.i18n_name = self.trAlgorithm('Poly Clip Data') self.group, self.i18n_group = self.trAlgorithm('Points') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input LAS layer'))) - self.addParameter(ParameterFile(self.MASK, self.tr('Mask layer'))) + self.INPUT, self.tr('Input LAS layer'), + optional=False)) + self.addParameter(ParameterFile(self.MASK, self.tr('Mask layer'), optional=False)) self.addOutput(OutputFile(self.OUTPUT, self.tr('Output clipped LAS file'), 'las')) - self.addParameter(ParameterBoolean(self.SHAPE, - self.tr('Use Shape attribute'), False)) - ## 'field' e 'value' box should appear or get activated if Shape attribute is switched ON + self.addParameter(ParameterString(self.SHAPE, self.tr("Use Shape attribute (shp column number,value)"), optional=True)) self.addParameter(ParameterString(self.FIELD, self.tr('Shape field index'))) self.addParameter(ParameterString(self.VALUE, self.tr("Shape value"))) + self.addParameter(ParameterBoolean(self.MULTIFILE, self.tr('Create a file per each polygon'), False)) self.addAdvancedModifiers() def processAlgorithm(self, feedback): @@ -67,6 +68,9 @@ class PolyClipData(FusionAlgorithm): commands.append('/verbose') if self.getParameterValue(self.SHAPE): commands.append('/shape:' + str(self.getParameterValue(self.FIELD)) + ',' + str(self.getParameterValue(self.VALUE))) + multiFile = self.getParameterValue(self.MULTIFILE) + if multiFile: + commands.append('/multifile') self.addAdvancedModifiersToCommand(commands) commands.append(self.getParameterValue(self.MASK)) outFile = self.getOutputValue(self.OUTPUT) diff --git a/python/plugins/processing/algs/lidar/fusion/ReturnDensity.py b/python/plugins/processing/algs/lidar/fusion/ReturnDensity.py new file mode 100644 index 00000000000..75fecd5dbd4 --- /dev/null +++ b/python/plugins/processing/algs/lidar/fusion/ReturnDensity.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + ReturnDensity.py #spellok + --------------------- + Date : November 2016 + Copyright : (C) 2016 by Niccolo' Marchi + Email : sciurusurbanus at hotmail dot it +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = "Niccolo' Marchi" +__date__ = 'November 2016' +__copyright__ = "(C) 2016 by Niccolo' Marchi" + +# This will get replaced with a git SHA1 when you do a git archive + +__revision__ = '$Format:%H$' + +import os +from processing.core.parameters import ParameterFile +from processing.core.parameters import ParameterNumber +from processing.core.parameters import ParameterBoolean +from processing.core.parameters import ParameterString +from processing.core.outputs import OutputFile +from .FusionAlgorithm import FusionAlgorithm +from .FusionUtils import FusionUtils + + +class ReturnDensity(FusionAlgorithm): # spellok + + INPUT = 'INPUT' + OUTPUT = 'OUTPUT' + CELLSIZE = 'CELLSIZE' + FIRST = 'FIRST' + ASCII = 'ASCII' + CLASS = 'CLASS' + + def defineCharacteristics(self): + self.name, self.i18n_name = self.trAlgorithm('Return Density') + self.group, self.i18n_group = self.trAlgorithm('Surface') + self.addParameter(ParameterFile( + self.INPUT, self.tr('Input LAS layer'), optional=False)) + self.addParameter(ParameterNumber( + self.CELLSIZE, self.tr('Cellsize'), 0, None, 10.0)) + self.addOutput(OutputFile( + self.OUTPUT, self.tr('Output file'))) + first = ParameterBoolean( + self.FIRST, self.tr('Use only first returns when computing return counts'), False) + first.isAdvanced = True + self.addParameter(first) + ascii = ParameterBoolean( + self.ASCII, self.tr('Output raster data in ASCII raster format instead of PLANS DTM format'), False) + ascii.isAdvanced = True + self.addParameter(ascii) + + class_var = ParameterString( + self.CLASS, self.tr('LAS class'), '', False, True) + class_var.isAdvanced = True + self.addParameter(class_var) + self.addAdvancedModifiers() + + def processAlgorithm(self, progress): + commands = [os.path.join(FusionUtils.FusionPath(), 'ReturnDensity.exe')] # spellok + commands.append('/verbose') + + first = self.getParameterValue(self.FIRST) + if first: + commands.append('/first') + + ascii = self.getParameterValue(self.ASCII) + if ascii: + commands.append('/ascii') + + class_var = self.getParameterValue(self.CLASS) + if class_var: + commands.append('/class:' + unicode(class_var)) + + self.addAdvancedModifiersToCommand(commands) + commands.append(self.getOutputValue(self.OUTPUT)) + commands.append(unicode(self.getParameterValue(self.CELLSIZE))) + + files = self.getParameterValue(self.INPUT).split(';') + if len(files) == 1: + commands.append(self.getParameterValue(self.INPUT)) + else: + FusionUtils.createFileList(files) + commands.append(FusionUtils.tempFileListFilepath()) + FusionUtils.runFusion(commands, progress) diff --git a/python/plugins/processing/algs/lidar/fusion/SplitDTM.py b/python/plugins/processing/algs/lidar/fusion/SplitDTM.py new file mode 100644 index 00000000000..52bc7b7784b --- /dev/null +++ b/python/plugins/processing/algs/lidar/fusion/SplitDTM.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + SplitDTM.py + --------------------- + Date : November 2016 + Copyright : (C) 2016 by Niccolo' Marchi + Email : sciurusurbanus at hotmail dot it +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = "Niccolo' Marchi" +__date__ = 'November 2016' +__copyright__ = "(C) 2016 by Niccolo' Marchi" + +# This will get replaced with a git SHA1 when you do a git archive + +__revision__ = '$Format:%H$' + +import os +from processing.core.parameters import ParameterFile +from processing.core.parameters import ParameterNumber +from processing.core.parameters import ParameterString +from processing.core.outputs import OutputFile +from .FusionAlgorithm import FusionAlgorithm +from .FusionUtils import FusionUtils + + +class SplitDTM(FusionAlgorithm): + + INPUT = 'INPUT' + OUTPUT = 'OUTPUT' + COLUMNS = 'COLUMNS' + ROWS = 'ROWS' + + def defineCharacteristics(self): + self.name, self.i18n_name = self.trAlgorithm('Split PLANS DTM files') + self.group, self.i18n_group = self.trAlgorithm('Points') + self.addParameter(ParameterFile( + self.INPUT, self.tr('Input PLANS DTM file'), optional=False)) + self.addParameter(ParameterNumber( + self.COLUMNS, self.tr('Number of columns of tiles'), 0, None, 1)) + self.addParameter(ParameterNumber( + self.ROWS, self.tr('Number of rows of tiles'), 0, None, 1)) + self.addOutput(OutputFile( + self.OUTPUT, self.tr('Output files'))) + self.addAdvancedModifiers() + + def processAlgorithm(self, progress): + commands = [os.path.join(FusionUtils.FusionPath(), 'SplitDTM.exe')] + commands.append('/verbose') + self.addAdvancedModifiersToCommand(commands) + files = self.getParameterValue(self.INPUT).split(';') + if len(files) == 1: + commands.append(self.getParameterValue(self.INPUT)) + else: + FusionUtils.createFileList(files) + commands.append(FusionUtils.tempFileListFilepath()) + outFile = self.getOutputValue(self.OUTPUT) + commands.append(outFile) + commands.append(unicode(self.getParameterValue(self.COLUMNS))) + commands.append(unicode(self.getParameterValue(self.ROWS))) + FusionUtils.runFusion(commands, progress) diff --git a/python/plugins/processing/algs/lidar/fusion/SurfaceStats.py b/python/plugins/processing/algs/lidar/fusion/SurfaceStats.py new file mode 100644 index 00000000000..a929e6d4c53 --- /dev/null +++ b/python/plugins/processing/algs/lidar/fusion/SurfaceStats.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + SurfaceStats.py + --------------------- + Date : November 2016 + Copyright : (C) 2016 by Niccolo' Marchi + Email : sciurusurbanus at hotmail dot it +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = "Niccolo' Marchi" +__date__ = 'November 2016' +__copyright__ = "(C) 2016 by Niccolo' Marchi" + +# This will get replaced with a git SHA1 when you do a git archive + +__revision__ = '$Format:%H$' + +import os +from processing.core.parameters import ParameterFile +from processing.core.outputs import OutputFile +from .FusionAlgorithm import FusionAlgorithm +from .FusionUtils import FusionUtils + + +class SurfaceStats(FusionAlgorithm): + + INPUT = "INPUT" + OUTPUT = "OUTPUT" + GROUND = 'GROUND' + + def defineCharacteristics(self): + self.name, self.i18n_name = self.trAlgorithm('Surface Statistics') + self.group, self.i18n_group = self.trAlgorithm('Surface') + self.addParameter(ParameterFile( + self.INPUT, self.tr('Input PLANS DTM layer'), optional=False)) + self.addOutput(OutputFile(self.OUTPUT, self.tr('Output file name'), 'csv')) + ground = ParameterFile( + self.GROUND, self.tr('Use the specified surface model to represent the ground surface')) + ground.isAdvanced = True + self.addParameter(ground) + self.addAdvancedModifiers() + + def processAlgorithm(self, progress): + commands = [os.path.join(FusionUtils.FusionPath(), "SurfaceStats.exe")] + commands.append('/verbose') + ground = self.getParameterValue(self.GROUND) + if ground: + gfiles = self.getParameterValue(self.GROUND).split(';') + if len(gfiles) == 1: + commands.append('/ground:' + unicode(ground)) + else: + FusionUtils.createGroundList(gfiles) + commands.append('/ground:' + unicode(FusionUtils.tempGroundListFilepath())) + self.addAdvancedModifiersToCommand(commands) + files = self.getParameterValue(self.INPUT).split(";") + if len(files) == 1: + commands.append(self.getParameterValue(self.INPUT)) + else: + FusionUtils.createFileList(files) + commands.append(FusionUtils.tempFileListFilepath()) + outFile = self.getOutputValue(self.OUTPUT) + commands.append(outFile) + FusionUtils.runFusion(commands, progress) diff --git a/python/plugins/processing/algs/lidar/fusion/TinSurfaceCreate.py b/python/plugins/processing/algs/lidar/fusion/TinSurfaceCreate.py index d06476e94f0..2647a623126 100644 --- a/python/plugins/processing/algs/lidar/fusion/TinSurfaceCreate.py +++ b/python/plugins/processing/algs/lidar/fusion/TinSurfaceCreate.py @@ -52,7 +52,8 @@ class TinSurfaceCreate(FusionAlgorithm): self.name, self.i18n_name = self.trAlgorithm('Tin Surface Create') self.group, self.i18n_group = self.trAlgorithm('Surface') self.addParameter(ParameterFile( - self.INPUT, self.tr('Input LAS layer'))) + self.INPUT, self.tr('Input LAS layer'), + optional=False)) self.addParameter(ParameterNumber(self.CELLSIZE, self.tr('Cell Size'), 0, None, 10.0)) self.addParameter(ParameterSelection(self.XYUNITS, diff --git a/python/plugins/processing/algs/lidar/fusion/TopoMetrics.py b/python/plugins/processing/algs/lidar/fusion/TopoMetrics.py new file mode 100644 index 00000000000..ce568e4f818 --- /dev/null +++ b/python/plugins/processing/algs/lidar/fusion/TopoMetrics.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + TopoMetrics.py + --------------------- + Date : August 2016 + Copyright : (C) 2016 by Niccolo' Marchi + Email : sciurusurbanus at hotmail dot it +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = "Niccolo' Marchi" +__date__ = 'August 2016' +__copyright__ = "(C) 2016 by Niccolo' Marchi" + +# This will get replaced with a git SHA1 when you do a git archive + +__revision__ = '$Format:%H$' + +import os +from processing.core.parameters import ParameterBoolean +from processing.core.parameters import ParameterFile +from processing.core.parameters import ParameterNumber +from processing.core.outputs import OutputFile +from .FusionAlgorithm import FusionAlgorithm +from .FusionUtils import FusionUtils + + +class TopoMetrics(FusionAlgorithm): + + INPUT = 'INPUT' + OUTPUT = 'OUTPUT' + CELLSIZE = 'CELLSIZE' + POINTSP = 'POINTSP' + LATITUDE = 'LATITUDE' + TPI = 'TPI' + SQUARE = 'SQUARE' + DISK = 'DISK' + + def defineCharacteristics(self): + self.name, self.i18n_name = self.trAlgorithm('Topographic Metrics') + self.group, self.i18n_group = self.trAlgorithm('Points') + self.addParameter(ParameterFile( + self.INPUT, self.tr('Input PLANS DTM surface files'), optional=False)) + self.addOutput(OutputFile( + self.OUTPUT, self.tr('Output file'))) + + self.addParameter(ParameterNumber( + self.CELLSIZE, self.tr('Size of the cell used to report topographic metrics'), 0, None, 5.0)) + self.addParameter(ParameterNumber( + self.POINTSP, self.tr('Spacing for the 3 by 3 array of points used to compute the metrics'), 0, None, 0.0)) + self.addParameter(ParameterNumber( + self.LATITUDE, self.tr('Latitude'), 2, None, 45.0)) + self.addParameter(ParameterNumber( + self.TPI, self.tr('TPI window size'), 0, None, 5.0)) + + square = ParameterBoolean( + self.SQUARE, self.tr('Use a square window for TPI'), False) + square.isAdvanced = True + self.addParameter(square) + + disk = ParameterBoolean( + self.DISK, self.tr('Do not load ground surface models into memory'), False) + disk.isAdvanced = True + self.addParameter(disk) + + self.addAdvancedModifiers() + + def processAlgorithm(self, progress): + commands = [os.path.join(FusionUtils.FusionPath(), 'TopoMetrics.exe')] + commands.append('/verbose') + + square = self.getParameterValue(self.SQUARE) + if square: + commands.append('/square') + disk = self.getParameterValue(self.DISK) + if disk: + commands.append('/disk') + self.addAdvancedModifiersToCommand(commands) + files = self.getParameterValue(self.INPUT).split(';') + if len(files) == 1: + commands.append(self.getParameterValue(self.INPUT)) + else: + FusionUtils.createFileList(files) + commands.append(FusionUtils.tempFileListFilepath()) + + commands.append(unicode(self.getParameterValue(self.CELLSIZE))) + commands.append(unicode(self.getParameterValue(self.POINTSP))) + commands.append(unicode(self.getParameterValue(self.LATITUDE))) + commands.append(unicode(self.getParameterValue(self.TPI))) + + outFile = self.getOutputValue(self.OUTPUT) + commands.append(outFile) + FusionUtils.runFusion(commands, progress) diff --git a/python/plugins/processing/algs/lidar/fusion/TreeSeg.py b/python/plugins/processing/algs/lidar/fusion/TreeSeg.py new file mode 100644 index 00000000000..a1e261cb884 --- /dev/null +++ b/python/plugins/processing/algs/lidar/fusion/TreeSeg.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + TreeSeg.py + --------------------- + Date : November 2016 + Copyright : (C) 2016 by Niccolo' Marchi + Email : sciurusurbanus at hotmail dot it +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = "Niccolo' Marchi" +__date__ = 'November 2016' +__copyright__ = "(C) 2016 by Niccolo' Marchi" + +# This will get replaced with a git SHA1 when you do a git archive + +__revision__ = '$Format:%H$' + +import os +from processing.core.parameters import ParameterBoolean +from processing.core.parameters import ParameterFile +from processing.core.parameters import ParameterNumber +from processing.core.outputs import OutputFile +from .FusionAlgorithm import FusionAlgorithm +from .FusionUtils import FusionUtils + + +class TreeSeg(FusionAlgorithm): + + INPUT = 'INPUT' + GROUND = 'GROUND' + HTTH = 'HTTH' + OUTPUT = 'OUTPUT' + HEIGHT = 'HEIGHT' + SHAPE = 'SHAPE' + ALIGN = 'ALIGN' + BUFF = 'BUFF' + + def defineCharacteristics(self): + self.name, self.i18n_name = self.trAlgorithm('Tree Segmentation') + self.group, self.i18n_group = self.trAlgorithm('Points') + self.addParameter(ParameterFile( + self.INPUT, self.tr('Input Canopy Height Model (in PLANS DTM format)'), optional=False)) + self.addParameter(ParameterNumber( + self.HTTH, self.tr('Minimum height for object segmentation'), 0, None, 2.0)) + self.addOutput(OutputFile( + self.OUTPUT, self.tr('Base name for output files'))) + + ground = ParameterFile( + self.GROUND, self.tr('Ground file for height normalization')) + ground.isAdvanced = True + self.addParameter(ground) + height = ParameterBoolean( + self.HEIGHT, self.tr("Normalize height model using ground model (select if a ground file is provided)"), False) + height.isAdvanced = True + self.addParameter(height) + buff = ParameterNumber( + self.BUFF, self.tr('Add a buffer to the data extent when segmenting'), 0, None, 0.0) + buff.isAdvanced + self.addParameter(buff) + shape = ParameterBoolean( + self.SHAPE, self.tr('Create output shapefiles'), False) + shape.isAdvanced = True + self.addParameter(shape) + align = ParameterBoolean( + self.ALIGN, self.tr('Align output grid to the input extent'), False) + align.isAdvanced = True + self.addParameter(align) + + self.addAdvancedModifiers() + + def processAlgorithm(self, progress): + commands = [os.path.join(FusionUtils.FusionPath(), 'TreeSeg.exe')] + commands.append('/verbose') + + ground = self.getParameterValue(self.GROUND) + if ground: + gfiles = self.getParameterValue(self.GROUND).split(';') + if len(gfiles) == 1: + commands.append('/ground:' + unicode(ground)) + else: + FusionUtils.createGroundList(gfiles) + commands.append('/ground:' + unicode(FusionUtils.tempGroundListFilepath())) + height = self.getParameterValue(self.HEIGHT) + if height: + commands.append('/height') + buff = self.getParameterValue(self.BUFF) + if buff != 0.0: + commands.append('/buffer:' + unicode(self.getParameterValue(self.BUFF))) + shape = self.getParameterValue(self.SHAPE) + if shape: + commands.append('/shape') + align = self.getParameterValue(self.ALIGN) + if align: + commands.append('/align:' + unicode(self.getParameterValue(self.INPUT))) + self.addAdvancedModifiersToCommand(commands) + + files = self.getParameterValue(self.INPUT).split(';') + if len(files) == 1: + commands.append(self.getParameterValue(self.INPUT)) + else: + FusionUtils.createFileList(files) + commands.append(FusionUtils.tempFileListFilepath()) + + commands.append(unicode(self.getParameterValue(self.HTTH))) + + outFile = self.getOutputValue(self.OUTPUT) + commands.append(outFile) + FusionUtils.runFusion(commands, progress)