tag:blogger.com,1999:blog-16997901865324172782024-03-13T07:23:52.424+01:00theBioBucket**a biologist's recycle-binUnknownnoreply@blogger.comBlogger166125tag:blogger.com,1999:blog-1699790186532417278.post-70328841475122826512023-11-16T17:38:00.003+01:002023-11-16T17:38:42.481+01:00Workflow for Replacing DOM With DEM Values in a Zone Specified by Vector Layer1. Create polygon file with same CRS as DOM and DEM and draw polygon mask (obv. polygons with holes don't work!) <div><br /></div><div>2. Use the "Rasterize (overwrite with fixed value)" algorithm, using the polygon mask as vector layer and the DOM as raster layer (set the DOM as reference layer!). Set the burn value to -9999. BEAWARE: The original file will be overwritten - if you don't want to alter the original file, make a copy of the DOM first!</div><div><br /></div><div>3. Use the raster calculator to rewrite the values in the DEM with values from the DOM by using this formula: </div><div><br /></div><div>(DOM@1 = -9999) * DGM@1 + (DOM@1 != -9999) * DOM@1
</div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-83167318180950400202023-10-04T10:07:00.000+02:002023-10-04T10:07:42.249+02:00Windows Batch Script for Zipping Shapefile ComponentsWindows Batch File to zip ESRI shapefile-components and delete original files.
Put the code to a text file and save with .bat extension. Save the file to the folder you want to run the commands.
<pre><code class="bash">@ECHO OFF
set /p $dum="Hit enter to zip Shapefiles in %~dp0 ..."
FOR %%F IN (*.shp) DO "C:\Program Files\7-Zip\7zG.exe" a "%%~nF.zip" "%%~nF.shp" "%%~nF.dbf" "%%~nF.prj" "%%~nF.shx"
for /f "delims=" %%F in ('dir /b /a-d ^| findstr /vile ".bat .zip"') do Echo "%%F"
set /p $dum="Hit enter to delete original files, listed above.."
for /f "delims=" %%F in ('dir /b /a-d ^| findstr /vile ".bat .zip"') do del "%%F"
Echo Done !!
set /p $dum="Hit [Enter] to exit..."
</code></pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-2609916194797903842023-08-24T14:56:00.009+02:002023-08-24T15:44:53.675+02:00QGIS3 Virtual Layer & SQL: Calculation of Intersection Areas from (Segmented) Line Buffers and Polygon Usecase: For a set of lines in one layer you would like to know the areas of (segmented) line buffers, that intersect with polygons from another layer. I.e., (segmented = with different buffer width segments) trail buffers, that intersect with wood patches. An inner buffer segment of, say 10 meters (5 meters to each side of the middle line) and an oute buffer segment, inbetween 5 and 10 meters offset from the middle line.
In QGIS Virtual Layers SQL you can not call Buffer function with specification of the end ("square", "flat", "round") and Buffer() will make round ends by default - so you need the workaround with ST_union() of single sided buffers to get the correct flat ends. Then, for the final calculations, all the feature's buffer polygons were merged into one polygon with outer ST_Union() call.
The ST_difference() call is used to make the outer buffer segment by clipping the narrower ("Breite_Forst") from the wider buffer ("Breite_Forst"+"Breite_F_bef").
The final output will be to poylgons, one with the inner, narrower buffer, and one with the outer wider buffer, and the calculated areas for each polygon, and merged into one table with the UNION ALL statement.
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8yrrcGYqxPoTjwufoYzaXXS-pyiO8wjBrq8jD1-P4QqCLGxmoeE7ebkDVyTx6bIB9HxE3z-0IN0YRgXvYykVtM74UUBGbwJpPKetQDaDNtItP86j78d9jKmqnBNSj-Xgt0xiJ5WHLyC2oUv14eaUXvPR7tBG0l444kF6tR2GhQCNuac50mRf-XhCOOpnG/s1225/2023-08-24%2015_41_19-Program%20Manager.jpg" style="display: block; padding: 1em 0; text"><img alt="" border="0" width="320" data-original-height="862" data-original-width="1225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8yrrcGYqxPoTjwufoYzaXXS-pyiO8wjBrq8jD1-P4QqCLGxmoeE7ebkDVyTx6bIB9HxE3z-0IN0YRgXvYykVtM74UUBGbwJpPKetQDaDNtItP86j78d9jKmqnBNSj-Xgt0xiJ5WHLyC2oUv14eaUXvPR7tBG0l444kF6tR2GhQCNuac50mRf-XhCOOpnG/s320/2023-08-24%2015_41_19-Program%20Manager.jpg"/></a></div>
<pre><code>
SELECT
T.geom as geometry,
ST_area(T.geom) AS Fl_Rod
FROM (
SELECT
ST_union(
ST_union(
intersection(st_SingleSidedBuffer(t.geometry,t.Breite_Forst/2,0), w.geometry),
intersection(st_SingleSidedBuffer(t.geometry,t.Breite_Forst/2,1), w.geometry)
)
) AS geom
FROM trails AS t, wood AS w
UNION ALL
SELECT
ST_difference(
ST_union(
ST_union(
intersection(st_SingleSidedBuffer(t.geometry,t.Breite_Forst/2+Breite_F_bef,0), w.geometry),
intersection(st_SingleSidedBuffer(t.geometry,t.Breite_Forst/2+Breite_F_bef,1), w.geometry)
)
),
ST_union(
ST_union(
intersection(st_SingleSidedBuffer(t.geometry,t.Breite_Forst/2,0), w.geometry),
intersection(st_SingleSidedBuffer(t.geometry,t.Breite_Forst/2,1), w.geometry)
)
)
) AS geom
FROM trails AS t, wood AS w
) as T
</code></pre>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-21469334948475976412023-04-12T11:37:00.004+02:002023-04-12T11:39:07.870+02:00QGIS3: Elevation Gain for LinestringZ GeometryUse this Expression in the QGIS3 Field Calculator to get the eöevation gain for a LinestringZ geometry!
<pre><code>array_sum(
array_filter(
array_foreach(generate_series(1,num_geometries(nodes_to_points($geometry))),
z(geometry_n( nodes_to_points($geometry), @element+1))-
z(geometry_n( nodes_to_points($geometry), @element))
), @element>0
)
)
</pre></code>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-2623751212345228202023-03-09T09:44:00.003+01:002023-05-02T15:34:01.991+02:00QGIS3: Neat trick to convert color name into color rgb string <pre><code>color_mix_rgb('blue', 'white', 0)</pre></code>
Arguments to the function are color1: a color string, color2: a color string, ratio:
the ratio at which the two colors will be mixed.
The output is:
<pre><code>'0,0,255,255'</pre></code>
The usecase is converting a color name, stored in a field (field name is "color_name_code"), to a color string to be used for symbolizing layer features, like so:
<pre><code>color_mix_rgb("color_name_code", 'white', 0.2)</pre></code> which will give me a bit of a pastel tone, by mixing white into the given "color_name_code" (blue, red, green, etc.) with a ratio of 0.2 Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-31564703305847945412023-02-27T16:45:00.004+01:002023-04-10T18:47:23.580+02:00QGIS3: Find Minimum/Maximum/Mean Raster Value (Elevation) for Polygon Overlay For finding raster value statistics (Min, Max, Mean) for a polygon overlay, I apply this expression in a virtual field by using the field calculator. The raster layer that I'm querying is named
<pre><code>'DGM_merged'</code></pre>
The functions is looking for the min. raster value at the polygon's nodes
<pre><code>
array_min(
array_foreach(
generate_series(1, num_points($geometry), 1),
raster_value('DGM_merged', 1,
point_n(nodes_to_points($geometry), @element)
)
)
)
</code></pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-42448799319078669732022-12-13T12:46:00.015+01:002023-04-10T18:47:36.233+02:00QGIS3: Virtual Layers & Spatialite/SQLite/SQL Queries - Intersecting Lines With PolygonsSQL and Spatialite make super effective table and geometry operations possible. With the implemantation of Virtual Layers, QGIS has now a built in functionality to run such queries very easily and without the need for preparation of databases.
The below SQL snippet, i.e., can be used to intersect features of a line and a polygon layer, and calculate the summed segment lengths for each single polygon. The usecase here was, that I needed to know the cummulated lengths of trail crossing single parcels.
<pre><code>
SELECT
t.Name AS Trail_Name,
g.GNR AS Parcel_NR,
SUM(LENGTH(INTERSECTION(t.geometry, g.geometry))) AS SUM_L_inP,
COLLECT(INTERSECTION(t.geometry, g.geometry)) as geom
FROM Trails AS t JOIN Parcels AS g ON INTERSECTS(t.geometry, g.geometry)
GROUP BY g.GNR
</code></pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-66566911312921024682022-09-09T17:24:00.011+02:002022-09-09T17:31:00.791+02:00QGIS REGEX Expression to Find Last Vaue of an XML/Html Image Source of the Description Field of a KML File <pre><code class="sh">if(
regexp_substr(description, 'img src="!?.*img src="(.*)"') = '',
regexp_substr(description, 'img src="(.*)"'),
regexp_substr(description, 'img src="!?.*img src="(.*)"')
)</code></pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-82952281957166818092022-07-07T00:25:00.015+02:002023-01-25T17:22:29.788+01:00GDAL: Bash Script for Converting All GPKG-Files From Directory To GPX-FormatSince lately QGIS (QGIS 3.12) comes equipped with a nice tool ("Split Vector Layers"), that will split your layers based on an attribute and ame your files accordingly. Th only drawback is, that you can not choose different output format - so you'll need to go with the only possibility, namely the GPKG-format. Now, I rather needed GPX files and had to find a way of converting the gpkg-files in batch mode. This I achieved by writing a small bash script looping over the files with GDAL's ogr2ogr command, and convert each file to GPX.
<pre><code class="sh"><br />
#!/bin/bash
## first two lines and last line prevent whitspace problems in filenames (see: https://unix.stackexchange.com/questions/9496/looping-through-files-with-spaces-in-the-names
## then loop over all files with gpkg extension an convert to gpx format preserving the old filename!
## the script would throw an error and discard attribute fields for all fieldnames that do not match the GPX XML definition (name, cmt, etc…).
## if you dont put the GPX_USE_EXTENSION=YES paramter..
## with <-t_srs epsg:4326=""> the target CRS, to which the input coordinates will be transformed, is given..
OIFS="$IFS"
IFS=$'\n'
for f in *.gpkg
do ogr2ogr -f GPX -dsco GPX_USE_EXTENSIONS=YES -t_srs EPSG:4326 -overwrite ${f%.*}.gpx $f
done
IFS="$OIFS"
read -p "Hit [Enter] to exit..."
</code></pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-29317222852593288702022-06-09T12:15:00.007+02:002023-02-27T16:40:23.095+01:00QGIS 3: Symbology with Geometry Generator - Draw One Convex Hull For All Features With Same Attribute I have a layer named "Trails" with an attribute "Trail ID", which contains unique, consecutive Feature/Trail IDs and an attribute "Schwierigkeit" (trail difficulty). For all features with the value "black" for the attribute "Schwierigkeit" I want to render one convex hull. The below code will select the last element of all the features in the layer and apply the code for drawing the polygon only once. The first <pre><code class="vba">array_foreach()</code></pre> in the code will create an array of all features (series generated from 1 to feature count number). Over this array, the second array_foreach() will apply the geometry function on each element that meets the condition of the <pre><code class="vba">array_filter()</code></pre> function. The <pre><code class="vba">collect_geometries()</code></pre> function finally puts all those single geometries within the resulting array into one multiline geometry, for which I then draw the hull.
The purpose of this procedure, is to check if the trails in my dataset show a spatial aggregation according to their trail difficulty..
<pre><code class="vba">
if($id = maximum($id),
convex_hull(
collect_geometries(
with_variable('my_arr',
array_foreach(
generate_series(1, layer_property( 'trails', 'feature_count'), 1),
get_feature('trails', 'Trail ID', @element)
),
array_foreach(
array_filter(@my_arr, attribute(@element, 'Schwierigkeit')='black') , geometry(@element)))))
, NULL)
</code></pre>
Unknownnoreply@blogger.comtag:blogger.com,1999:blog-1699790186532417278.post-61890645706635770192022-02-28T12:13:00.006+01:002022-02-28T12:13:45.871+01:00QGIS 3: Geometry Generator Expression for Points at Line Intersections A solution for symbolizing line intersections between the current layer's features and another layer's features ('Tracks Subset=Detail'). The <pre><code class="vba">generate_series</code></pre> is used with an <pre><code class="vba">aggregate</code></pre> which yields the number if features in the other layer used for the intersection. The <pre><code class="vba">array_foreach</code></pre> iterates over all features of the other layer and intersects each line with the input layer's current feature. The <pre><code class="vba">array_filter</code></pre> is needed to filter out the epmty geometries that could result after the intersection. If you wouldn't do this, the code would break when calling <pre><code class="vba">collect_geometries</code></pre>, which is needed to finally convert the array of geometries into a valid, digestible geometry collection, fed into the geometry generator with checking Point/Multi-POint as geometry type..
<pre><code class="vba">with_variable ('my_series', generate_series(1, aggregate(layer:='Tracks Subset=Detail', aggregate:='max', expression:="id")),
collect_geometries(
array_filter(
array_foreach(@my_series, if(is_empty_or_null(
intersection(geometry(get_feature('Tracks Subset=Detail', 'id', @element)),
$geometry)), 'x', intersection(geometry(get_feature('Tracks Subset=Detail', 'id', @element)),
$geometry))
),
@element != 'x'
)
)
)
</code></pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-34049187018294059472020-11-25T08:53:00.007+01:002020-11-25T10:35:44.180+01:00QGIS3: Aggregate Data of Intersecting Features: Concatenate String Attributes of Polygons Crossed by Line Features <pre><code class="vba">regexp_replace(aggregate(layer:='Prcl_Lyr', aggregate:='concatenate', expression:="Prp_Ownr",filter:=intersects( $geometry, geometry(@parent)), concatenator:='/'), '[/]{2,}', '/')</code></pre>
Polygon Layer "Parcell_Lyr"
Field holding Owner Data "Prop_Ownr"
The parent layer is the line layer with the lines, for which we want to collect the polygon data, intersected by the single line features.
For aggregated NULL or empty strings the concatenator character would be replicated without strings inbetween - for this, the regex "[/]{2,}" which matches a forward slash, repeated twice or more, will replace those doubled slashes with a single one. Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-53299496492294641692019-08-27T11:39:00.004+02:002020-11-25T10:35:22.629+01:00QGIS 3: Layout expression to get all features of a layer within the current map viewIn a map layout template you can insert an expression which gets all feature's names of a certain layer, which are contained in the current layout's view/extent. For wxample you could concatenate all feature's names contained in the current map view like so:<br />
<br />
<pre><code class="vba">aggregate(layer:='Corridors_86ef2ea9_d1a1_4d9f_9735_7b7b2fb54cb2',
aggregate:='concatenate',
expression:="Name", filter:=within($geometry, map_get( item_variables('Main Map'),
'map_extent')), concatenator:=', ')
</code></pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-21164318214434249282019-08-13T22:24:00.011+02:002023-04-10T20:52:15.230+02:00Aggregation of Different Layers in QGIS 3.x with Field Calculator Expression Alone!!Here's an example of how to "spatially aggregate" Polygon attribute values over features of a point layer by intersecting the two layers. Go in "Edit mode" with the target layer and check "Virtual Field" with type "decimal". Then use this in expression builder, where "layer" is the point layer, and aggregate the attribute values that intersect the target layer's geometry. With "Expression" you can define the attribute, that should aggregated!<br />
<pre><code class="vba">aggregate(layer:='BIKFFH_Karwendel BIKFFH_PL', aggregate:='sum', expression:="LNUMMER",
filter:=intersects($geometry,geometry(@parent)))
</code></pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-40913353916904131172019-02-20T12:15:00.002+01:002022-12-14T18:00:30.246+01:00Return Excel Row Indices of non-empty Cells in ColumnColumn with Data in A1:A20<br />
<br />
Formula in Cell B1 <br />
<br />
<pre><code>=WENNFEHLER(AGGREGAT(15;6;ZEILE($A$1:$A$20)*N(LÄNGE($A$1:$A$20)>0);SUMMENPRODUKT(N(LÄNGE(Datenablage!$A$1:$A$20)=0))+ZEILE());"")
SUMMENPRODUKT(N(LÄNGE(Datenablage!$A$1:$A$20)=0)) is needed because each LEN=0 will be a smallest value, so if you have 3 cells with LEN=0 the ksmallest with k=4 will be the first non empty value..
</pre></code><br />
..for details on aggregate check: <a href="https://www.youtube.com/watch?v=He3dblboncw">https://www.youtube.com/watch?v=He3dblboncw</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-2281378558135892572017-07-14T20:07:00.001+02:002022-12-13T14:06:27.722+01:00Excel VBA User Defined Function for Transformation of Braun-Blanquet Values to Precentages of Vegetation Cover <pre><code>Function Transf_BraunBlanquet(ByVal BB_Str As String) As String
'Transformation of Braun-Blanquet 'Artmächtigkeit' to percentage cover (similar to usage in TurboVeg or twinspan)
'The key value mapping can be altered depending on specific requirements
'This UDF is used in the UDF SumKum_BraunBlanquet(), which will apply the Transformation on a range of values and
'will sum the transformed percentages. This cumulative sum can be used to check if the Braun-Blanquet estimation for
'a vegetation layer is reasonable.
With CreateObject("Scripting.Dictionary")
'~~> first transfer your list in Dictionary
.Add "r", "0"
.Add "+", "0"
.Add "1", "1"
.Add "2m", "2"
.Add "2a", "10"
.Add "2b", "20"
.Add "3", "37,5"
.Add "4", "67,5"
.Add "5", "87,5"
If Len(BB_Str) = 0 Then
'~~> case: empty cell
Transf_BraunBlanquet = 0
Exit Function
End If
For Each elem In .keys
key = elem
If key = BB_Str Then
Transf_BraunBlanquet = .Item(elem) * 1
Exit Function
End If
Next elem
End With
End Function
Function SumKum_BraunBlanquet(Rng As Range) As Double
'See comments on Transf_BraunBlanquet() for explanations
Dim Sum As Double
Dim RngArr As Variant
RngArr = Application.Transpose(Rng) 'dumps range values to array
For Each elem In RngArr
Sum = Sum + Transf_BraunBlanquet(elem)
Next elem
SumKum_BraunBlanquet = Sum
End Function
</pre></code>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-20314600540551098692016-12-16T08:00:00.001+01:002022-12-13T14:06:08.193+01:00VBA Macro to Export Data from Excel Spreadsheet to CSVResources: http://stackoverflow.com/questions/13496686/how-to-save-semi-colon-delimited-csv-file-using-vba<br />
and: http://stackoverflow.com/questions/35655426/excel-vba-finding-recording-user-selection<br />
<br />
<pre><code>Sub Export_CSV()
'***************************************************************************************
'author: kay cichini
'date: 26102014
'update: 16122016
'purpose: export current spreadsheet to csv.file to the same file path as source file
'
' !!NOTE!! files with same name and path will be overwritten
'***************************************************************************************
Dim MyPath As String
Dim MyFileName As String
Dim WB1 As Workbook, WB2 As Workbook
Set WB1 = ActiveWorkbook
'(1) either used range in active sheet..
'ActiveWorkbook.ActiveSheet.UsedRange.Copy
'(2) or alternatively, user selected input range:
Dim rng As Range
Set rng = Application.InputBox("select cell range with changes", "Cells to be copied", Default:="Select Cell Range", Type:=8)
Application.ScreenUpdating = False
rng.Copy
Set WB2 = Application.Workbooks.Add(1)
WB2.Sheets(1).Range("A1").PasteSpecial xlPasteValues
MyFileName = "CSV_Export_" & Format(Date, "ddmmyyyy")
FullPath = WB1.Path & "\" & MyFileName
Application.DisplayAlerts = False
If MsgBox("Data copied to " & WB1.Path & "\" & MyFileName & vbCrLf & _
"Warning: Files in directory with same name will be overwritten!!", vbQuestion + vbYesNo) <> vbYes Then
Exit Sub
End If
If Not Right(MyFileName, 4) = ".csv" Then MyFileName = MyFileName & ".csv"
With WB2
.SaveAs Filename:=FullPath, FileFormat:=xlCSV, CreateBackup:=False
.Close False
End With
Application.DisplayAlerts = True
End Sub
</pre></code>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-1699790186532417278.post-78718000776942646612016-10-18T14:35:00.001+02:002016-10-18T14:37:15.625+02:00Collect GPX-Files from Subdirectories and Convert to Single KML FileReference: https://cran.r-project.org/web/packages/sp/vignettes/intro_sp.pdf<br />
<br />
<pre class="brush:r">library(sp)
library(rgdal)
# here, m ygpx files reside in subdirectories..
setwd("D:/WEB/gardaweb")
files <- dir(pattern="*.gpx$", recursive = T, include.dirs = T)
# extract spatial lines
spl <- lapply(files, function(x) {readOGR(x, "tracks")@lines[[1]]} )
str(spl)
# apply ID to ID slot for latter merge with attribute data
for(i in 1:length(spl)) {slot(spl[[i]], "ID") <- as.character(i)}
tracksSL <- SpatialLines(spl, proj4string = CRS("+proj=longlat +datum=WGS84"))
# view data
summary(tracksSL)
plot(tracksSL)
# make dataframe for merging with spatial data
names <- sub("[.]gpx$", "", basename(files))
df <- data.frame(names = names, row.names = sapply(slot(tracksSL, "lines"), function(x) slot(x, "ID")))
# spatial dataframe
tracksSLDF <- SpatialLinesDataFrame(tracksSL, data = df)
# write ressult to KML
writeOGR(tracksSLDF, dsn="tracks_collection.kml", layer= "Wolfi_Garda_Tracks", driver="KML", dataset_options=c("NameField=names"))
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-5110149653235116912016-07-06T15:46:00.003+02:002022-12-13T14:05:48.662+01:00VBA Subroutine to Clear All Filters in Excel-Table<pre><code>
Sub filter_clear()
'****************************************************************************************************************
'author: kay cichini
'date: 06072016
'purpose: clear all filters in a preformated excel tabel
'****************************************************************************************************************
Dim SelectedCell As Range
Dim TableName As String
Dim ActiveTable As ListObject
Set SelectedCell = ActiveCell
'Determine if ActiveCell is inside a Table
On Error GoTo NoTableSelected
TableName = SelectedCell.ListObject.Name
Set ActiveTable = ActiveSheet.ListObjects(TableName)
If ActiveTable.ShowAutoFilter Then
'MsgBox "AutoFilters are turned on"
If ActiveTable.AutoFilter.FilterMode Then
'MsgBox "Filter is actually set"
ActiveTable.AutoFilter.ShowAllData
End If
End If
On Error GoTo 0
Exit Sub
'Error Handling
NoTableSelected:
MsgBox "There is no Table currently selected! (You need to activate a cell in the Table to be cleared!)", vbCritical
End Sub
</pre></code>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-91110628702582953972016-02-23T15:11:00.000+01:002016-02-23T15:46:22.520+01:00List Files Recursively and Write to File in Windows Shellcd into the directory to be listed and then do:<br />
<pre class="shell">dir /a-d /b /s > C:\WINDOWS\Temp\file_list.txt
start notepad C:\WINDOWS\Temp\file_list.txt
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-22243828374892895362016-01-25T21:57:00.001+01:002016-02-01T20:47:40.516+01:00HTML Legend for Corine Land Cover ClassesFor anyone who might benefit from it, I'll post a HTML legend for CORINE Land Cover (CLC) Classes, which I tailored for HTML labelling of CLC-Rasters embeded in my QGIS via WMS.. Choose HTML, CSS or Result from the JSFiddle menu!<br />
</br><br />
<iframe width="100%" height="300" src="//jsfiddle.net/gimoya/8nd8pj39/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe><br />
<br />
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-89086126619472331712015-10-21T18:16:00.000+02:002015-10-21T20:24:27.856+02:00QGIS Processing Script for Quick Feature Selection and ZoomHere's a little QGIS processsing script which might come in handy for you as well, if you've got to visually check many features and need to find/select/zoom them manually by attribute values. Using the attribute table's functions (find by expression, etc.) is rather cumbersome, if you have to iterate over loads of features for visual control - that's where the below script kicks in: You call the processing script from the processing toolbox panel (I like to have this one always visible) and just type in the feature's attribute value you're searching for, then, with one go, this feature is selected and zoomed. The zoom-value (2500) is hard coded into the script as well as the default layer (the one you're currently working with), for the sake of not having to put all of this manually each time (so you'll have to change this for your own purpose;).<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg183ohYUpEgYlqGbu17ilvK0-lcTYK30UwKj4Oi7KLc73GCzhEkn40HQrkIHBjJNMIRCk7vNTUIBJDUDU2fZyWeoi3tAtqt168aL7HrCpGIB_yDPIn9M5EU8U1yVzQ4e9DqB_fUyC28sz/s1600/Clipboard06.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg183ohYUpEgYlqGbu17ilvK0-lcTYK30UwKj4Oi7KLc73GCzhEkn40HQrkIHBjJNMIRCk7vNTUIBJDUDU2fZyWeoi3tAtqt168aL7HrCpGIB_yDPIn9M5EU8U1yVzQ4e9DqB_fUyC28sz/s400/Clipboard06.jpg" /></a></div><br />
<br />
<pre class="brush:py">from PyQt4.QtCore import *
from qgis.core import *
from qgis.utils import *
#===============================================
##[User scripts]=group
##Gst_Nr=string
##Name_Layer=string 81127GST_V2
#===============================================
# Gst_Nr is the field in which we are searching
# 81127GST_V2 is the default layer for searching
#===============================================
canvas = iface.mapCanvas()
# First zoom to desired scale
canvas.zoomScale( 2500 )
allLayers = canvas.layers()
n = len(allLayers)
for i in range(0, n):
if allLayers[i].name() == Name_Layer:
break
tarL = allLayers[i]
# Get a featureIterator from an expression
expr = QgsExpression( "\"GNR\"='" + Gst_Nr+ "'" )
it = tarL.getFeatures( QgsFeatureRequest( expr ) )
# Build a list of feature Ids from the result obtained above
ids = [j.id() for j in it]
# Select features with the ids
tarL.setSelectedFeatures( ids )
# Zoom to selected features
canvas.zoomToSelected( tarL )
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-13665740088617304002015-04-25T14:23:00.003+02:002015-04-25T14:29:18.670+02:00Offline Map Tiles with Mapbox-Studio and MOBACI just found I neat workaround on how to get your Mapbox projects (Mapbox is a free, fully customizeable Tool for map design) to any local tile storage format that it also available in MOBAC (MOBAC is a free software for the creation of local map tiles from variable sources, in a bunch of different formats, to be used on almost any mobile device)!<br />
<br />
<li/>Get <a href="https://www.mapbox.com/design/">Mapbox-Studio</a> and design your custom map<br />
<li/>Upload your project to mapbox<br />
<li/>Create an account and connect to it<br />
<li/>Get your username, project ID and an access token, which are put to the URL for fetching the tiles back from the Mapbox server: http://api.tiles.mapbox.com/v4/your_username.your_project_id/{$z}/{$x}/{$y}.png?access_token=your_private_or_public_api_key<br />
<br />
<li/>Use the following XML (replacing user, project ID and access token) for a custom mapsource in <a href="http://mobac.sourceforge.net/MOBAC/README.HTM">MOBAC</a>.<br />
<br />
<pre class="brush:xml"><!--xml version="1.0" encoding="UTF-8"-->
<custommapsource>
<name>MAPBOX</name>
<minzoom>0</minZoom>
<maxzoom>18</maxZoom>
<tiletype>png</tileType>
<tileupdate>None</tileUpdate>
<url>http://api.tiles.mapbox.com/v4/gimoya.ganok9hk/{$z}/{$x}/{$y}.png?access_token=pk.eyJ1IjoiZ2ltb3lhIiwiYSI6IkZrTld6NmcifQ.eY6Ymt2kVLvPQ6A2Dt9zAQ</url>
<backgroundcolor>#000000</backgroundColor>
</customMapSource>
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-17189360975722724792015-04-08T00:27:00.001+02:002015-04-10T18:17:26.834+02:00QspatiaLite Use Case: Find Number of Species from Point DataHere's a short follow up on some previous posting about the use of QspatiaLite for the aggregation of species distribution data. In this case the species data comes as a point layer. For each cell of a 1000 x 1000 m grid (1) the number of individuals per species, (2) the total number of individuals and (3) the number of different species should be calculated.<br />
<br />
<br />
There is a layer with 10 different species (variabel name is "sp") across the whole extent with names "1", "2", "3", .. , "10" and a layer with the grid cells (variable name = "id") numbered consecutively, from 1 to 150.<br />
<br />
In the attribute table of the below screenshot you see that I selected the grid cell with id=1 and the points (=species) within this cell. There are 8 individuals - "4", "5", "6" and "10" occure once, whereas "2" and "8" occure twice.<br />
<br />
The query table in the screenshot is the result for (3).<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-UIeLcyFNIOM/VSRW38O0-gI/AAAAAAAALqI/TWeE-5ewDqM/s1600/sp_nr.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-UIeLcyFNIOM/VSRW38O0-gI/AAAAAAAALqI/TWeE-5ewDqM/s640/sp_nr.jpg" /></a></div><br />
For (1) you have to query for points/species within grid cells and group over grid cells and species and take the count from that aggregation<br />
<pre class="brush:sql">SELECT
t.gID AS gID,
t.sp AS Sp,
count(*) AS NrIndSp
FROM (SELECT
g.id AS gID,
s.sp AS sp
FROM grid AS g JOIN Sp_distr AS s
ON within(s.Geometry, g.Geometry)
) as t GROUP BY t.gId, t.sp
</pre><br />
For (2) you simple need to query for points/species within grid cells and aggregate over grid cells:<br />
<br />
<pre class="brush:sql">Select
t.gID,
count(*) as NrInd
From (SELECT
g.id AS gID,
s.sp AS sp
FROM grid AS g JOIN Sp_distr AS s
ON within(s.Geometry, g.Geometry)
) as t
GROUP BY t.gID
ORDER BY t.gID
</pre><br />
For (3) you'll first need to aggregate over grid cells and points/species, and then again aggregate over this query table by grid cells which will finally give you the distinct species!<br />
<br />
<pre class="brush:sql">SELECT
v.gID,
count(*) AS SpNr
FROM (SELECT
t.gID,
t.sp
FROM (SELECT
g.id AS gID,
s.sp AS sp
FROM grid AS g JOIN Sp_distr AS s
ON within(s.Geometry, g.Geometry)
) as t GROUP BY t.gId, t.sp
) as v GROUP BY v.gId
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1699790186532417278.post-13803325089321650682015-02-18T22:49:00.003+01:002022-12-13T13:37:30.354+01:00Python Processing Script for Splitting Layer and Saving each Feature to ShapefileA script for a common task: Split a Layer by distinct values of an attribute-field. The script will use the value for the name of the files and remove the field from the new files.<br />
<br />
Put this processing script to the appropiate director (in my case it's "C:\Users\Kay\.qgis2\processing\scripts") to make it work. Then it will be easily accessible from your processing toolbox.<br />
<br />
<pre><code>##[User scripts]=group
##input=vector
##class_field=field input
##output=output file
from qgis.core import *
from PyQt4.QtCore import *
from processing.core.VectorWriter import VectorWriter
layer = processing.getObject(input)
provider = layer.dataProvider()
fields = provider.fields()
class_field_index = layer.fieldNameIndex(class_field)
fields.remove( class_field_index )
inFeat = QgsFeature()
outFeat = QgsFeature()
inGeom = QgsGeometry()
nElement = 0
writers = {}
feats = processing.features(layer)
nFeat = len(feats)
for inFeat in feats:
progress.setPercentage(int(100 * nElement / nFeat))
nElement += 1
featAttr = inFeat.attributes()
classField = featAttr[class_field_index]
if classField not in writers:
outputFile = output + '_' + classField + '.shp'
writers[classField] = VectorWriter(outputFile, None, fields, provider.geometryType(), layer.crs())
inGeom = inFeat.geometry()
outFeat.setGeometry(inGeom)
del featAttr[class_field_index]
outFeat.setAttributes(featAttr)
writers[classField].addFeature(outFeat)
for writer in writers.values():
del writer
</code></pre>Unknownnoreply@blogger.com0