Skip to content

Commit

Permalink
Merge pull request #4053 from alexbruy/lidartools-update
Browse files Browse the repository at this point in the history
[processing] fixes and new tools for LiDAR processing
  • Loading branch information
alexbruy committed Jan 25, 2017
2 parents 0de0015 + 514e55b commit 66c7129
Show file tree
Hide file tree
Showing 30 changed files with 1,073 additions and 86 deletions.
Expand Up @@ -140,6 +140,15 @@
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


Expand Down Expand Up @@ -213,7 +222,8 @@ def _loadAlgorithms(self):
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')
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/lidar/fusion/ASCII2DTM.py
Expand Up @@ -51,7 +51,7 @@ def defineCharacteristics(self):
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(
Expand Down
48 changes: 29 additions & 19 deletions python/plugins/processing/algs/lidar/fusion/CanopyMaxima.py
Expand Up @@ -32,7 +32,7 @@
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

Expand All @@ -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))
Expand Down
34 changes: 28 additions & 6 deletions python/plugins/processing/algs/lidar/fusion/CanopyModel.py
Expand Up @@ -45,6 +45,7 @@ class CanopyModel(FusionAlgorithm):

INPUT = 'INPUT'
OUTPUT_DTM = 'OUTPUT_DTM'
ASPECT = 'ASPECT'
CELLSIZE = 'CELLSIZE'
XYUNITS = 'XYUNITS'
ZUNITS = 'ZUNITS'
Expand All @@ -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(
Expand All @@ -70,7 +73,7 @@ def defineCharacteristics(self):
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(
Expand All @@ -82,13 +85,21 @@ def defineCharacteristics(self):
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()
Expand All @@ -98,7 +109,12 @@ def processAlgorithm(self, feedback):
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))
Expand All @@ -108,11 +124,17 @@ def processAlgorithm(self, feedback):
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))
Expand Down
34 changes: 33 additions & 1 deletion python/plugins/processing/algs/lidar/fusion/Catalog.py
Expand Up @@ -29,6 +29,7 @@
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
Expand All @@ -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,
Expand All @@ -67,6 +74,16 @@ def defineCharacteristics(self):
'', 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)
Expand All @@ -85,6 +102,21 @@ def processAlgorithm(self, feedback):
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)
Expand Down
12 changes: 9 additions & 3 deletions python/plugins/processing/algs/lidar/fusion/ClipData.py
Expand Up @@ -51,10 +51,11 @@ def defineCharacteristics(self):
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(
Expand All @@ -74,7 +75,12 @@ def processAlgorithm(self, feedback):
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')
Expand Down
15 changes: 8 additions & 7 deletions python/plugins/processing/algs/lidar/fusion/CloudMetrics.py
Expand Up @@ -32,11 +32,11 @@

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):
Expand All @@ -52,10 +52,11 @@ def defineCharacteristics(self):
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(
Expand All @@ -66,15 +67,15 @@ def defineCharacteristics(self):
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)

def processAlgorithm(self, feedback):
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:
Expand All @@ -83,7 +84,7 @@ def processAlgorithm(self, feedback):
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:
Expand Down

0 comments on commit 66c7129

Please sign in to comment.