[GRASS-SVN] r68243 - in grass-addons/grass7/vector: . v.stream.order v.stream.order/testsuite v.stream.order/testsuite/data
svn_grass at osgeo.org
svn_grass at osgeo.org
Sun Apr 10 05:53:24 PDT 2016
Author: huhabla
Date: 2016-04-10 05:53:24 -0700 (Sun, 10 Apr 2016)
New Revision: 68243
Added:
grass-addons/grass7/vector/v.stream.order/
grass-addons/grass7/vector/v.stream.order/Makefile
grass-addons/grass7/vector/v.stream.order/stream_network.png
grass-addons/grass7/vector/v.stream.order/stream_network_order_drwal.png
grass-addons/grass7/vector/v.stream.order/stream_network_order_scheidegger.png
grass-addons/grass7/vector/v.stream.order/stream_network_order_shreve.png
grass-addons/grass7/vector/v.stream.order/stream_network_order_strahler.png
grass-addons/grass7/vector/v.stream.order/testsuite/
grass-addons/grass7/vector/v.stream.order/testsuite/data/
grass-addons/grass7/vector/v.stream.order/testsuite/data/stream_network.txt
grass-addons/grass7/vector/v.stream.order/testsuite/data/stream_network_outlets.txt
grass-addons/grass7/vector/v.stream.order/testsuite/generate_manpage_images.sh
grass-addons/grass7/vector/v.stream.order/testsuite/generate_stream_outflow_points.sh
grass-addons/grass7/vector/v.stream.order/testsuite/test_stream_order.py
grass-addons/grass7/vector/v.stream.order/v.stream.order.html
grass-addons/grass7/vector/v.stream.order/v.stream.order.py
Log:
New module to compute different stream orders on vector networks.
AUTHOR(S): IGB-Berlin,Johannes Radinger; Implementation: Soeren Gebbert"
This tool was developed as part of the BiodivERsA-net project 'FISHCON'
and has been funded by the German Federal Ministry for Education and
Research (grant number 01LC1205).
Added: grass-addons/grass7/vector/v.stream.order/Makefile
===================================================================
--- grass-addons/grass7/vector/v.stream.order/Makefile (rev 0)
+++ grass-addons/grass7/vector/v.stream.order/Makefile 2016-04-10 12:53:24 UTC (rev 68243)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../..
+
+PGM = v.stream.order
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script
Added: grass-addons/grass7/vector/v.stream.order/stream_network.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass7/vector/v.stream.order/stream_network.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: grass-addons/grass7/vector/v.stream.order/stream_network_order_drwal.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass7/vector/v.stream.order/stream_network_order_drwal.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: grass-addons/grass7/vector/v.stream.order/stream_network_order_scheidegger.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass7/vector/v.stream.order/stream_network_order_scheidegger.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: grass-addons/grass7/vector/v.stream.order/stream_network_order_shreve.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass7/vector/v.stream.order/stream_network_order_shreve.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: grass-addons/grass7/vector/v.stream.order/stream_network_order_strahler.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass7/vector/v.stream.order/stream_network_order_strahler.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: grass-addons/grass7/vector/v.stream.order/testsuite/data/stream_network.txt
===================================================================
--- grass-addons/grass7/vector/v.stream.order/testsuite/data/stream_network.txt (rev 0)
+++ grass-addons/grass7/vector/v.stream.order/testsuite/data/stream_network.txt 2016-04-10 12:53:24 UTC (rev 68243)
@@ -0,0 +1,539 @@
+ORGANIZATION:
+DIGIT DATE:
+DIGIT NAME: soeren
+MAP NAME:
+MAP DATE: Mon Nov 23 09:27:02 2015
+MAP SCALE: 1
+OTHER INFO:
+ZONE: 0
+MAP THRESH: 0.000000
+VERTI:
+L 3 1
+ 641045.70521951 218398.66077254
+ 641049.6221644 218261.56770124
+ 641026.12049504 218155.8101891
+ 1 5
+L 2 1
+ 640769.59784873 218298.21972805
+ 641026.12049504 218155.8101891
+ 1 4
+L 2 1
+ 640587.42266689 218394.74382764
+ 640769.59784873 218298.21972805
+ 1 2
+L 4 1
+ 641754.51490227 218445.12286994
+ 641813.68865794 218350.44486086
+ 641821.57849203 218216.31768133
+ 641801.85390681 218113.74983816
+ 1 6
+L 4 1
+ 641801.85390681 218113.74983816
+ 641880.75224771 218192.64817906
+ 641999.09975906 218338.61010972
+ 642121.39218745 218409.61861653
+ 1 7
+L 2 1
+ 640882.68823532 217640.35979276
+ 640866.90856714 217305.04184393
+ 1 9
+L 4 1
+ 640397.46343879 217608.8004564
+ 640567.09487172 217525.95719845
+ 640701.22205125 217399.71985301
+ 640866.90856714 217305.04184393
+ 1 10
+L 6 1
+ 640866.90856714 217305.04184393
+ 641008.92558076 217198.52908372
+ 641178.5570137 217044.67731896
+ 641296.90452505 216910.55013943
+ 641415.2520364 216851.37638376
+ 641456.98443339 216796.63031084
+ 1 11
+L 2 1
+ 641613.66222916 217223.5773043
+ 641527.48944149 216965.05894128
+ 1 4
+L 2 1
+ 641527.48944149 216965.05894128
+ 641456.98443339 216796.63031084
+ 1 4
+L 3 1
+ 641527.48944149 216965.05894128
+ 641876.80733066 216886.88063716
+ 642089.83285109 216989.44848033
+ 1 12
+L 2 1
+ 642610.56190103 216646.24069742
+ 642429.09571696 216807.98229626
+ 1 15
+L 2 1
+ 642638.17632035 216875.04588603
+ 642429.09571696 216807.98229626
+ 1 14
+L 4 1
+ 642429.09571696 216807.98229626
+ 642235.79478176 216851.37638376
+ 642129.28202154 216953.94422693
+ 642089.83285109 216989.44848033
+ 1 14
+L 2 1
+ 641111.49342393 216523.94826902
+ 641570.57583532 216479.35777441
+ 1 16
+L 2 1
+ 641456.98443339 216796.63031084
+ 641570.57583532 216479.35777441
+ 1 4
+L 3 1
+ 642835.4221726 217356.32576552
+ 642752.57891465 217285.31725871
+ 642598.38529023 217185.55940265
+ 1 13
+L 4 1
+ 642089.83285109 216989.44848033
+ 642243.68461585 217178.80449849
+ 642456.71013628 217218.25366894
+ 642598.38529023 217185.55940265
+ 1 12
+L 3 1
+ 642598.38529023 217185.55940265
+ 642713.1297442 217159.07991327
+ 642870.926426 217092.0163235
+ 1 12
+L 2 1
+ 642598.38529023 217185.55940265
+ 642598.38529023 217185.55940265
+ 1 13
+L 6 1
+ 641756.22516769 217996.07572149
+ 641849.21322931 217926.33467527
+ 641910.86354075 217814.96637073
+ 641916.82969993 217504.72609381
+ 641795.51779677 217411.25626679
+ 641655.59356064 217351.01110956
+ 1 17
+L 2 1
+ 641801.85390681 218113.74983816
+ 641756.22516769 217996.07572149
+ 1 8
+L 2 1
+ 641655.59356064 217351.01110956
+ 641613.66222916 217223.5773043
+ 1 8
+L 3 1
+ 641756.22516769 217996.07572149
+ 641726.90048295 217920.44890295
+ 641705.76772964 217817.13322006
+ 1 8
+L 5 1
+ 641705.76772964 217817.13322006
+ 641691.39622955 217746.87255297
+ 641687.4513125 217573.29620299
+ 641667.72672728 217387.88510188
+ 641655.59356064 217351.01110956
+ 1 8
+L 3 1
+ 641282.29449313 217827.21623271
+ 641499.52584836 217821.16315379
+ 641705.76772964 217817.13322006
+ 1 18
+L 3 1
+ 641026.12049504 218155.8101891
+ 641268.97107847 217850.28848736
+ 641282.29449313 217827.21623271
+ 1 4
+L 3 1
+ 641282.29449313 217827.21623271
+ 641429.56581913 217572.18539988
+ 641613.66222916 217223.5773043
+ 1 4
+L 6 1
+ 641570.57583532 216479.35777441
+ 641974.02115942 216122.91578904
+ 642030.89764886 216016.47550165
+ 642034.11888304 216010.44719198
+ 642248.20730201 215609.79600791
+ 642659.48651589 215155.43040019
+ 1 4
+L 4 1
+ 643891.13814168 216140.36775244
+ 643813.99670971 216258.10993807
+ 643700.31459945 216258.10993807
+ 643639.41346895 216262.17001344
+ 1 22
+L 2 1
+ 643692.19444871 216505.77453544
+ 643639.41346895 216262.17001344
+ 1 21
+L 3 1
+ 643639.41346895 216262.17001344
+ 643509.49105721 216176.90843074
+ 643347.08804255 216156.60805391
+ 1 21
+L 4 1
+ 643168.44472642 215852.10240141
+ 643079.12306835 215982.02481314
+ 642932.96035515 216091.64684804
+ 642709.65620999 216180.96850611
+ 1 23
+L 3 1
+ 643347.08804255 216156.60805391
+ 643225.28578155 215998.26511461
+ 643168.44472642 215852.10240141
+ 1 19
+L 6 1
+ 643311.00699542 215576.83439857
+ 643347.08804255 215640.97848235
+ 643440.46977598 215734.36021578
+ 643574.45226308 215779.02104481
+ 643688.13437335 215787.14119555
+ 643773.39595605 215783.08112018
+ 1 24
+L 3 1
+ 643168.44472642 215852.10240141
+ 643221.22570618 215681.57923601
+ 643311.00699542 215576.83439857
+ 1 19
+L 5 1
+ 643311.00699542 215576.83439857
+ 643343.02796718 215539.47659818
+ 643448.58992672 215381.13365888
+ 643456.71007745 215234.97094568
+ 643424.22947452 215113.16868469
+ 1 19
+L 4 1
+ 640567.86448829 216432.09912471
+ 640567.86448829 216226.52319892
+ 640600.75663642 216086.73156938
+ 640584.31056236 215971.60905094
+ 1 27
+L 6 1
+ 640370.51159953 215511.11897717
+ 640641.87182158 215535.78808826
+ 640839.22471033 215486.44986607
+ 640913.23204362 215428.88860685
+ 641127.03100644 215346.65823654
+ 641127.03100644 215346.65823654
+ 1 28
+L 4 1
+ 640773.44041408 215848.26349546
+ 640946.12419174 215700.24882889
+ 641044.80063612 215511.11897717
+ 641127.03100644 215346.65823654
+ 1 25
+L 4 1
+ 641127.03100644 215346.65823654
+ 641283.26871004 215206.866607
+ 641571.07500615 215124.63623668
+ 641784.87396897 215108.19016262
+ 1 25
+L 2 1
+ 640584.31056236 215971.60905094
+ 640773.44041408 215848.26349546
+ 1 29
+L 2 1
+ 639498.86967419 217279.07193896
+ 639753.78382216 217163.94942052
+ 1 25
+L 3 1
+ 639753.78382216 217163.94942052
+ 639975.80582202 216966.59653176
+ 640132.04352562 216687.01327269
+ 1 25
+L 2 1
+ 640132.04352562 216687.01327269
+ 640214.27389593 216423.87608767
+ 1 25
+L 2 1
+ 640132.04352562 216687.01327269
+ 640166.20300793 216826.57359053
+ 1 31
+L 2 1
+ 640214.27389593 216423.87608767
+ 640370.51159953 216144.2928286
+ 1 25
+L 2 1
+ 640370.51159953 216144.2928286
+ 640584.31056236 215971.60905094
+ 1 25
+L 4 1
+ 639768.06562446 216349.33606465
+ 639696.87549629 216420.52619282
+ 639612.50201105 216504.89967806
+ 639483.30511178 216562.90644916
+ 1 34
+L 5 1
+ 639768.06562446 216349.33606465
+ 639599.31865399 216367.79276455
+ 639422.66166927 216378.3394502
+ 639240.73134172 216373.06610737
+ 639185.36124204 216312.42266486
+ 1 33
+L 5 1
+ 639768.06562446 216349.33606465
+ 639652.05208226 216315.05933627
+ 639512.30849733 216228.04917962
+ 639454.30172623 216104.12562318
+ 639420.02499786 215961.74536684
+ 1 35
+L 3 1
+ 639420.02499786 215961.74536684
+ 639288.19142717 215819.3651105
+ 639166.90454214 215792.99839636
+ 1 35
+L 4 1
+ 639628.32203954 215761.3583394
+ 639543.9485543 215782.45171071
+ 639480.66844037 215824.63845333
+ 639432.57555378 215849.9504989
+ 1 38
+L 3 1
+ 639420.02499786 215961.74536684
+ 639417.38832644 215887.91856725
+ 639432.57555378 215849.9504989
+ 1 36
+L 4 1
+ 639432.57555378 215849.9504989
+ 639449.02838341 215808.81842484
+ 639509.67182592 215721.80826819
+ 639538.67521147 215666.43816851
+ 1 36
+L 4 1
+ 639936.81259494 215945.92533836
+ 639923.62923787 216048.75552349
+ 639942.08593777 216109.398966
+ 639957.90596625 216148.94903721
+ 1 39
+L 2 1
+ 639786.52232436 215993.3854238
+ 639957.90596625 216148.94903721
+ 1 37
+L 2 1
+ 639498.86967419 216777.46668003
+ 639720.89167404 216736.35149487
+ 1 26
+L 4 1
+ 639720.89167404 216736.35149487
+ 639918.2445628 216645.89808753
+ 640156.71263671 216489.66038393
+ 640214.27389593 216423.87608767
+ 1 26
+L 4 1
+ 639686.32881064 217048.05398928
+ 639678.4187964 216966.31717545
+ 639665.23543933 216892.49037587
+ 639665.23543933 216892.49037587
+ 1 41
+L 3 1
+ 639443.75504058 217029.59728938
+ 639551.85856854 216968.95384687
+ 639665.23543933 216892.49037587
+ 1 40
+L 3 1
+ 639665.23543933 216892.49037587
+ 639712.69552477 216821.3002477
+ 639720.89167404 216736.35149487
+ 1 40
+L 2 1
+ 640545.8836915 216837.12027618
+ 640406.14010658 216781.7501765
+ 1 42
+L 3 1
+ 640353.4066783 216897.7637187
+ 640414.05012082 216871.39700456
+ 640414.05012082 216871.39700456
+ 1 46
+L 2 1
+ 640427.23347788 216929.40377566
+ 640414.05012082 216871.39700456
+ 1 45
+L 3 1
+ 640414.05012082 216871.39700456
+ 640387.68340668 216818.66357629
+ 640406.14010658 216781.7501765
+ 1 45
+L 2 1
+ 640166.20300793 217137.70081734
+ 640063.3728228 217311.72113065
+ 1 31
+L 4 1
+ 640150.91939902 217380.57237139
+ 640179.08811888 217311.35780259
+ 640192.77006852 217286.40836501
+ 640202.42791533 217275.14087706
+ 1 49
+L 2 1
+ 640257.15571392 217334.69759905
+ 640202.42791533 217275.14087706
+ 1 47
+L 4 1
+ 640202.42791533 217275.14087706
+ 640173.45437491 217220.41307848
+ 640167.82063093 217153.61297138
+ 640166.20300793 217137.70081734
+ 1 47
+L 4 1
+ 640313.49315364 217267.89749195
+ 640250.71714938 217238.11913096
+ 640209.67130044 217185.00097351
+ 640187.13632455 217161.66117706
+ 1 50
+L 2 1
+ 640187.13632455 217161.66117706
+ 640166.20300793 217137.70081734
+ 1 50
+L 5 1
+ 640299.81120399 217188.22025578
+ 640320.73653874 217200.29256429
+ 640350.51489974 217230.07092529
+ 640363.39202882 217251.80108061
+ 640372.24505506 217277.55533876
+ 1 52
+L 3 1
+ 640187.13632455 217161.66117706
+ 640228.18217349 217177.75758841
+ 640299.81120399 217188.22025578
+ 1 51
+L 3 1
+ 640299.81120399 217188.22025578
+ 640352.12454087 217181.78169124
+ 640370.63541392 217182.58651181
+ 1 51
+L 4 1
+ 640014.90472313 217113.37194301
+ 640080.90000965 217109.34784018
+ 640106.65426781 217106.93337847
+ 640126.774782 217098.8851728
+ 1 53
+L 3 1
+ 640016.51436426 217180.97687067
+ 640075.26626568 217143.15030401
+ 640126.774782 217098.8851728
+ 1 48
+L 4 1
+ 640496.992243 217076.35019691
+ 640466.40906144 217078.76465861
+ 640433.41141818 217079.56947918
+ 640430.56728114 217079.88549441
+ 1 55
+L 2 1
+ 640430.56728114 217079.88549441
+ 640524.79032019 217124.51746028
+ 1 32
+L 2 1
+ 639923.75454847 217316.53019876
+ 639766.66255648 217232.77558234
+ 1 57
+L 2 1
+ 639766.66255648 217232.77558234
+ 639753.78382216 217163.94942052
+ 1 30
+L 2 1
+ 639696.17129704 217379.58537484
+ 639775.58233648 217280.4444143
+ 1 56
+L 2 1
+ 639791.79566719 217367.09123033
+ 639775.58233648 217280.4444143
+ 1 30
+L 2 1
+ 639775.58233648 217280.4444143
+ 639766.66255648 217232.77558234
+ 1 30
+L 6 1
+ 640286.93407491 217099.68999337
+ 640266.81356073 217036.10916854
+ 640274.8617664 216995.0633196
+ 640272.4473047 216974.94280542
+ 640270.032843 216953.2126501
+ 640270.99789385 216947.66888143
+ 1 54
+L 3 1
+ 640166.20300793 216826.57359053
+ 640247.93982175 216924.13043283
+ 640270.99789385 216947.66888143
+ 1 32
+L 3 1
+ 640270.99789385 216947.66888143
+ 640374.50004961 217053.32733211
+ 640430.56728114 217079.88549441
+ 1 32
+L 2 1
+ 643330.84774108 216725.01860524
+ 643202.29377332 216520.61063111
+ 1 20
+L 3 1
+ 642993.86148565 216692.5380023
+ 643127.84397275 216591.03611814
+ 643202.29377332 216520.61063111
+ 1 19
+L 4 1
+ 643202.29377332 216520.61063111
+ 643278.06676132 216448.93348031
+ 643363.32834402 216314.95099321
+ 643347.08804255 216156.60805391
+ 1 19
+L 5 1
+ 639957.90596625 216148.94903721
+ 640037.00610866 216183.22576559
+ 640129.28960814 216188.49910842
+ 640195.20639348 216188.49910842
+ 640207.3392106 216189.4820258
+ 1 37
+L 3 1
+ 640370.51159953 216144.2928286
+ 640255.84983599 216164.76906569
+ 640207.3392106 216189.4820258
+ 1 33
+L 6 1
+ 640207.3392106 216189.4820258
+ 640206.384856 216189.96820644
+ 640205.09925849 216190.62313348
+ 640116.10625107 216235.95919386
+ 639968.4526519 216301.8759792
+ 639768.06562446 216349.33606465
+ 1 33
+L 5 1
+ 640409.61787735 216585.33800325
+ 640466.78354909 216657.82662005
+ 640532.70033443 216718.47006257
+ 640603.8904626 216752.74679095
+ 640656.62389088 216781.7501765
+ 1 44
+L 4 1
+ 640409.61787735 216585.33800325
+ 640445.69017778 216589.2731633
+ 640540.61034867 216583.99982047
+ 640627.62050533 216581.36314906
+ 1 43
+L 3 1
+ 640221.51282885 216510.13508436
+ 640300.67325003 216573.45313481
+ 640409.61787735 216585.33800325
+ 1 43
+L 4 1
+ 640406.14010658 216781.7501765
+ 640276.9432073 216655.18994864
+ 640224.20977903 216570.8164634
+ 640221.51282885 216510.13508436
+ 1 42
+L 3 1
+ 640221.51282885 216510.13508436
+ 640218.9364362 216452.16624978
+ 640214.27389593 216423.87608767
+ 1 42
+L 3 1
+ 640126.774782 217098.8851728
+ 640148.50493732 217067.49717067
+ 640166.20300793 217045.44843503
+ 1 48
+L 2 1
+ 640166.20300793 216826.57359053
+ 640166.20300793 217045.44843503
+ 1 31
+L 2 1
+ 640166.20300793 217045.44843503
+ 640166.20300793 217137.70081734
+ 1 31
Added: grass-addons/grass7/vector/v.stream.order/testsuite/data/stream_network_outlets.txt
===================================================================
--- grass-addons/grass7/vector/v.stream.order/testsuite/data/stream_network_outlets.txt (rev 0)
+++ grass-addons/grass7/vector/v.stream.order/testsuite/data/stream_network_outlets.txt 2016-04-10 12:53:24 UTC (rev 68243)
@@ -0,0 +1,29 @@
+ORGANIZATION:
+DIGIT DATE:
+DIGIT NAME: soeren
+MAP NAME:
+MAP DATE: Mon Nov 23 09:41:14 2015
+MAP SCALE: 1
+OTHER INFO:
+ZONE: 0
+MAP THRESH: 0.000000
+VERTI:
+P 1 1
+ 641762.6178191 215109.77637672
+ 1 1
+P 1 1
+ 642632.27087271 215183.86995156
+ 1 2
+P 1 1
+ 643421.88123234 215105.44974461
+ 1 3
+
+P 1 1
+ 641762.6178191 215109.77637672
+ 1 4
+P 1 1
+ 642632.27087271 215183.86995156
+ 1 5
+P 1 1
+ 643421.88123234 215105.44974461
+ 1 6
Added: grass-addons/grass7/vector/v.stream.order/testsuite/generate_manpage_images.sh
===================================================================
--- grass-addons/grass7/vector/v.stream.order/testsuite/generate_manpage_images.sh (rev 0)
+++ grass-addons/grass7/vector/v.stream.order/testsuite/generate_manpage_images.sh 2016-04-10 12:53:24 UTC (rev 68243)
@@ -0,0 +1,68 @@
+#!/bin/bash
+# Author: IGB-Berlin,Johannes Radinger; Implementation: Soeren Gebbert"
+# This tool was developed as part of the BiodivERsA-net project 'FISHCON'
+# and has been funded by the German Federal Ministry for Education and
+# Research (grant number 01LC1205).
+
+# Generate the map and images for the HTML documentation
+export GRASS_OVERWRITE=1
+
+# Import the stream network and the outlet points
+v.in.ascii input=data/stream_network.txt output=stream_network \
+ format=standard
+v.in.ascii input=data/stream_network_outlets.txt output=stream_network_outlets \
+ format=standard
+
+# Compute the different stream orders
+v.stream.order input=stream_network points=stream_network_outlets \
+ output=stream_network_order threshold=25 \
+ order=strahler,shreve,drwal,scheidegger
+
+# Set the correct region to visualize the 3 stream network
+n=216770
+s=215080
+w=642660
+e=644040
+g.region s=${s} n=${n} e=${e} w=${w} -p
+
+export GRASS_RENDER_WIDTH=400
+export GRASS_RENDER_HIGHT=800
+d.mon start=ps output=map.ps
+d.erase
+d.vect map=stream_network display=shape,dir \
+ width=3 size=10 label_size=20
+
+convert map.ps stream_network.pdf
+convert stream_network.pdf stream_network.png
+
+d.erase
+d.vect map=stream_network_order display=shape,dir \
+ width=3 width_column=strahler width_scale=3 size=15 \
+ attribute_column=strahler label_size=35 where="network = 3"
+
+convert map.ps stream_network_order_strahler.pdf
+convert stream_network_order_strahler.pdf stream_network_order_strahler.png
+
+d.erase
+d.vect map=stream_network_order display=shape,dir \
+ width=3 width_column=shreve width_scale=3 size=15 \
+ attribute_column=shreve label_size=35 where="network = 3"
+
+convert map.ps stream_network_order_shreve.pdf
+convert stream_network_order_shreve.pdf stream_network_order_shreve.png
+
+d.erase
+d.vect map=stream_network_order display=shape,dir \
+ width=3 width_column=drwal width_scale=3 size=15 \
+ attribute_column=drwal label_size=35 where="network = 3"
+
+convert map.ps stream_network_order_drwal.pdf
+convert stream_network_order_drwal.pdf stream_network_order_drwal.png
+
+d.erase
+d.vect map=stream_network_order display=shape,dir \
+ width=3 width_column=scheidegger width_scale=3 size=15 \
+ attribute_column=scheidegger label_size=35 where="network = 3"
+
+convert map.ps stream_network_order_scheidegger.pdf
+convert stream_network_order_scheidegger.pdf stream_network_order_scheidegger.png
Added: grass-addons/grass7/vector/v.stream.order/testsuite/generate_stream_outflow_points.sh
===================================================================
--- grass-addons/grass7/vector/v.stream.order/testsuite/generate_stream_outflow_points.sh (rev 0)
+++ grass-addons/grass7/vector/v.stream.order/testsuite/generate_stream_outflow_points.sh 2016-04-10 12:53:24 UTC (rev 68243)
@@ -0,0 +1,20 @@
+#!/bin/bash
+# This script creates the water outlet points
+# for different stream networks in the "streams at PERMANENT"
+# vector map layer in the nc location
+# Author: IGB-Berlin,Johannes Radinger; Implementation: Soeren Gebbert"
+# This tool was developed as part of the BiodivERsA-net project 'FISHCON'
+# and has been funded by the German Federal Ministry for Education and
+# Research (grant number 01LC1205).
+
+cat > points.csv << EOF
+640781.56098|214897.033189
+642228.347134|214979.370612
+638470.926725|214984.99142
+645247.580918|223346.644849
+638470.926725|214984.99142
+645247.580918|223346.644849
+EOF
+
+v.in.ascii output=stream_outflow input=points.csv x=1 y=2
+
Added: grass-addons/grass7/vector/v.stream.order/testsuite/test_stream_order.py
===================================================================
--- grass-addons/grass7/vector/v.stream.order/testsuite/test_stream_order.py (rev 0)
+++ grass-addons/grass7/vector/v.stream.order/testsuite/test_stream_order.py 2016-04-10 12:53:24 UTC (rev 68243)
@@ -0,0 +1,188 @@
+"""Test v.stream.order
+
+ at author
+IGB-Berlin,Johannes Radinger; Implementation: Soeren Gebbert"
+This tool was developed as part of the BiodivERsA-net project 'FISHCON'
+and has been funded by the German Federal Ministry for Education and
+Research (grant number 01LC1205).
+
+(C) 2014 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+"""
+
+from grass.gunittest.case import TestCase
+from grass.pygrass.vector import VectorTopo
+
+
+class TestStreamOrder(TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.runModule("v.in.ascii", input="data/stream_network.txt",
+ output="stream_network", format="standard",
+ overwrite=True)
+
+ cls.runModule("v.in.ascii", input="data/stream_network_outlets.txt",
+ output="stream_network_outlets", format="standard")
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.runModule("g.remove", flags="f", type="vector",
+ name="stream_network,stream_network_outlets")
+
+ def tearDown(self):
+ pass
+ self.runModule("g.remove", flags="f", type="vector",
+ pattern="stream_network_order_test_*")
+
+ def test_strahler(self):
+ self.assertModule("v.stream.order", input="stream_network",
+ points="stream_network_outlets",
+ output="stream_network_order_test_strahler",
+ threshold=25,
+ order=["strahler"],
+ overwrite=True, verbose=True)
+
+ # Check the strahler value
+ v = VectorTopo(name="stream_network_order_test_strahler",
+ mapset="")
+ v.open(mode="r")
+
+ self.assertTrue(v.exist(), True)
+ self.assertEqual(v.num_primitive_of("line"), 101)
+ # feature 4
+ self.assertEqual(v.read(4).attrs.cat, 41)
+ self.assertEqual(v.read(4).attrs["outlet_cat"], 1)
+ self.assertEqual(v.read(4).attrs["network"], 1)
+ self.assertEqual(v.read(4).attrs["reversed"], 0)
+ self.assertEqual(v.read(4).attrs["strahler"], 4)
+
+ v.close()
+
+ def test_all(self):
+ self.assertModule("v.stream.order", input="stream_network",
+ points="stream_network_outlets",
+ output="stream_network_order_test_all",
+ threshold=25,
+ order=["strahler", "shreve", "drwal", "scheidegger"],
+ overwrite=True, verbose=True)
+
+ # Check all values
+ v = VectorTopo(name="stream_network_order_test_all",
+ mapset="")
+ v.open(mode="r")
+ self.assertTrue(v.exist(), True)
+ self.assertEqual(v.num_primitive_of("line"), 101)
+ # feature 4
+ self.assertEqual(v.read(4).attrs.cat, 41)
+ self.assertEqual(v.read(4).attrs["outlet_cat"], 1)
+ self.assertEqual(v.read(4).attrs["network"], 1)
+ self.assertEqual(v.read(4).attrs["reversed"], 0)
+ self.assertEqual(v.read(4).attrs["strahler"], 4)
+ self.assertEqual(v.read(4).attrs["shreve"], 32)
+ self.assertEqual(v.read(4).attrs["drwal"], 6)
+ self.assertEqual(v.read(4).attrs["scheidegger"], 64)
+ v.close()
+
+ # Check for column copy
+ self.assertModule("v.stream.order",
+ input="stream_network_order_test_all",
+ points="stream_network_outlets",
+ output="stream_network_order_test_all_2",
+ threshold=25,
+ order=["strahler", "shreve", "drwal", "scheidegger"],
+ columns=["strahler", "shreve", "drwal", "scheidegger"],
+ overwrite=True, verbose=True)
+
+ # Check all values and their copies
+ v = VectorTopo(name="stream_network_order_test_all_2",
+ mapset="")
+ v.open(mode="r")
+ self.assertTrue(v.exist(), True)
+ self.assertEqual(v.num_primitive_of("line"), 101)
+ # feature 4
+ self.assertEqual(v.read(4).attrs.cat, 4)
+ self.assertEqual(v.read(4).attrs["outlet_cat"], 1)
+ self.assertEqual(v.read(4).attrs["network"], 1)
+ self.assertEqual(v.read(4).attrs["reversed"], 0)
+ self.assertEqual(v.read(4).attrs["strahler"], 4)
+ self.assertEqual(v.read(4).attrs["shreve"], 32)
+ self.assertEqual(v.read(4).attrs["drwal"], 6)
+ self.assertEqual(v.read(4).attrs["scheidegger"], 64)
+ self.assertEqual(v.read(4).attrs["strahler_1"], 4)
+ self.assertEqual(v.read(4).attrs["shreve_1"], 32)
+ self.assertEqual(v.read(4).attrs["drwal_1"], 6)
+ self.assertEqual(v.read(4).attrs["scheidegger_1"], 64)
+ # feature 7
+ self.assertEqual(v.read(7).attrs.cat, 7)
+ self.assertEqual(v.read(7).attrs["outlet_cat"], 1)
+ self.assertEqual(v.read(7).attrs["network"], 1)
+ self.assertEqual(v.read(7).attrs["reversed"], 0)
+ self.assertEqual(v.read(7).attrs["strahler"], 2)
+ self.assertEqual(v.read(7).attrs["strahler_1"], 2)
+ self.assertEqual(v.read(7).attrs["shreve"], 4)
+ self.assertEqual(v.read(7).attrs["drwal"], 3)
+ self.assertEqual(v.read(7).attrs["scheidegger"], 8)
+ v.close()
+
+
+class TestStreamOrderFails(TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.runModule("v.in.ascii", input="data/stream_network.txt",
+ output="stream_network", format="standard",
+ overwrite=True)
+
+ cls.runModule("v.in.ascii", input="data/stream_network_outlets.txt",
+ output="stream_network_outlets", format="standard")
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.runModule("g.remove", flags="f", type="vector",
+ name="stream_network,stream_network_outlets")
+
+ def test_error_handling_1(self):
+ # No input points
+ self.assertModuleFail("v.stream.order", input="stream_network",
+ output="stream_network_order", threshold=25,
+ order=["strahler", "shreve", "drwal", "scheidegger"])
+
+ def test_error_handling_2(self):
+ # No input network
+ self.assertModuleFail("v.stream.order",
+ points="stream_network_outlets",
+ output="stream_network_order", threshold=25,
+ order=["strahler", "shreve", "drwal", "scheidegger"])
+
+ def test_error_handling_3(self):
+ # No output
+ self.assertModuleFail("v.stream.order", input="stream_network",
+ points="stream_network_outlets",
+ threshold=25,
+ order=["strahler", "shreve", "drwal", "scheidegger"],
+ overwrite=True, verbose=True)
+
+ def test_error_handling_4(self):
+ # Recursion limit is below 1000
+ self.assertModuleFail("v.stream.order", input="stream_network",
+ points="stream_network_outlets",
+ output="stream_network_order", threshold=25,
+ order=["strahler", "shreve", "drwal", "scheidegger"],
+ recursionlimit=0,
+ overwrite=True, verbose=True)
+
+ def test_error_handling_5(self):
+ # Horton order is not implemented
+ self.assertModuleFail("v.stream.order", input="stream_network",
+ points="stream_network_outlets",
+ output="stream_network_order", threshold=25,
+ order=["horton"],
+ overwrite=True, verbose=True)
+
+if __name__ == '__main__':
+ from grass.gunittest.main import test
+ test()
Added: grass-addons/grass7/vector/v.stream.order/v.stream.order.html
===================================================================
--- grass-addons/grass7/vector/v.stream.order/v.stream.order.html (rev 0)
+++ grass-addons/grass7/vector/v.stream.order/v.stream.order.html 2016-04-10 12:53:24 UTC (rev 68243)
@@ -0,0 +1,198 @@
+<h2>DESCRIPTION</h2>
+
+The module <i>v.stream.order </i> is designed to compute different
+stream order approaches based on a stream network vector map and a water
+outlet vector point map. It requires two inputs:
+<ol>
+ <li>A vector line map with one or several independent stream networks</li>
+ <li>A vector point map that defines the water outlet points in the stream network</li>
+</ol>
+A single output vector map containing all detected networks and all specified orders
+is generated as output.
+
+<p>
+ The direction of the stream flow will be adjusted in outlet direction and stored in the
+ output vector map.<br><br>
+
+ To determine the outlet stream network segment, a nearest neighbor search is performed.
+ The threshold of the search can be adjusted with the <i>threshold</i> option.
+ It is required to specify the threshold as floating point value
+ that is interpreted using the locations projection unit. <br><br>
+
+ It is required that the vector line direction of the network segment that was found
+ at the outlet point, is directed to the outlet point. Since, the depth-first search
+ network traversing will be performed in upstream direction. Stream networks in
+ downstream direction will be detected. However, the stream order will not be computed.
+ The stream order table entries will be empty. <br><br>
+
+ The output vector map contains a column for each specified order algorithm,
+ the network id, the outlet category of the vector point input map
+ and the column <i>reversed</i>. The column reversed indicates if the
+ stream network segment was reversed in direction to point to
+ the water outlet point (0 - not reversed, 1 - reversed).<br><br>
+
+ In addition all columns from the stream network input map
+ are copied to the output vector map. The input vector map columns that
+ should be copied will be automagically renamed in the output vector map,
+ if the column names are conflicting with each other. Use the <i>columns</i>
+ parameter to specifiy a subset of columns that should be copied.
+ The keyword <i>all</i> is used to copy all columns to the output vector map
+ that are found in the input vector map (default).
+
+</p>
+
+<h2>Note</h2>
+<p>
+ Be aware that the stream network map must be topological correct.
+ Each independent stream network must be properly connected.
+ The implemented stream order algorithms rely on topological relations between lines and nodes
+ and are not designed to handle loops and channels in the stream networks correctly.<br><br>
+
+ The network traversing method, that is used to compute the stream order numbers,
+ is recursively implemented. In case of large stream networks, or networks
+ with many loops, the maximum recursion depth of Python may be reached.
+ The module will stop then with an <i>maximum recursion depth exceeded</i> exception.
+ This parameter can be adjusted with the <i>recursionlimit</i> option. The default in Python is 1000.
+ The default in v.stream.order is 10000.
+</p>
+
+<h2>Supported stream order algorithms</h2>
+
+The following algorithm examples are based on this stream network.
+Be aware of the wrong stream directions that will be adjusted by v.stream.order.<br>
+<img src="stream_network.png" border="0" height="240" width="200"><br>
+
+<h3>Strahler's stream order</h3>
+
+<img src="stream_network_order_strahler.png" border="0" height="240" width="200"><br>
+
+Strahler's stream order is a modification of Horton's streams order which fixes
+the ambiguity of Horton's ordering.
+In Strahler's ordering the main channel is not determined; instead the ordering
+is based on the hierarchy of tributaries. The
+ordering follows these rules:
+<ol>
+ <li>if the node has no children, its Strahler order is 1.
+ <li>if the node has one and only one tributuary with Strahler greatest order i,
+ and all other tributaries have order less than i, then the order remains i.
+ <li>if the node has two or more tributaries with greatest order i, then the
+ Strahler order of the node is i + 1.
+</ol>
+Strahler's stream ordering starts in initial links which assigns order one. It
+proceeds downstream. At every node it verifies that there are at least 2 equal
+tributaries with maximum order. If not it continues with highest order, if yes
+it increases the node's order by 1 and continues downstream with new order.
+<p>
+ <b>Advantages and disadvantages of Strahler's ordering: </b>
+ Strahler's stream order has a good mathematical background. All catchments with
+ streams in this context are directed graphs, oriented from the root towards the
+ leaves. Equivalent definition of the Strahler number of a tree is that it is the
+ height of the largest complete binary tree that can be homeomorphically embedded
+ into the given tree; the Strahler number of a node in a tree is equivalent to
+ the height of the largest complete binary tree that can be embedded below that
+ node.
+</p>
+<p>
+ The disadvantage of that methods is the lack of distinguishing a main
+ channel which may interfere with the analytical process in highly elongated
+ catchments. It is not able to handle loops in the ordered graph correctly.
+</p>
+
+<p>
+<h3>Shreve's stream magnitude</h3>
+
+<img src="stream_network_order_shreve.png" border="0" height="240" width="200"><br>
+
+That ordering method is similar to Consisted Associated Integers proposed by
+Scheidegger. It assigns magnitude of 1 for every initial channel. The magnitude
+of the following channel is the sum of magnitudes of its tributaries. The number
+of a particular link is the number of initials which contribute to it.
+
+<h3>Scheidegger's stream magnitude</h3>
+
+<img src="stream_network_order_scheidegger.png" border="0" height="240" width="200"><br>
+
+That ordering method is similar to Shreve's stream magnitude. It assigns
+magnitude of 2 for every initial channel. The magnitude of the following channel
+is the sum of magnitudes of its tributaries. The number of a particular link is
+the number of streams -1 contributing to it.
+
+<h3>Drwal's stream hierarchy </h3>
+
+<img src="stream_network_order_drwal.png" border="0" height="240" width="200"><br>
+
+That ordering method is a compromise between Strahler ordering and Shreve
+magnitude. It assigns order of 1 for every initial channel. The order of the
+following channel is calculated according Strahler formula, except, that streams
+which do not increase order of next channel are not lost. To increase next
+channel to the higher order R+1 are require two channels of order R, or one R and
+two R-1 or one R, and four R-2 or one R, one R-1 and two R-2 etc. The the order
+of particular link show the possible value of Strahler'order if the network was
+close to idealized binary tree. Drwal's order is computed based on
+Shreve's magnitude with the formula: <b>floor(log(shreve,2))+1</b>.
+<p>
+ <b>Advantages and disadvantages of Drwal's hierarhy:</b>
+ The main advantages of Drwal's hierarchy is that it produces natural stream
+ ordering with whcich takes into advantage both ordering and magnitude. It shows
+ the real impact of particular links of the network run-off. The main
+ disadvantage is that it minimize bifurcation ratio of the network.
+</p>
+
+<h2>Examples</h2>
+
+<h3>Stream order computation based on North Carolina location</h3>
+
+<div class="code"><pre>
+# We need to generate 4 outlet points that will lead to
+# 4 stream networks and therefore 4 output vector maps
+cat > points.csv << EOF
+640781.56098|214897.033189
+642228.347134|214979.370612
+638470.926725|214984.99142
+645247.580918|223346.644849
+EOF
+
+v.in.ascii output=streams_outlets input=points.csv x=1 y=2
+
+v.stream.order input=streams at PERMANENT points=streams_outlets \
+ output=streams_order threshold=25 order=strahler,shreve
+
+v.info streams_order
+v.db.select streams_order | less
+
+</pre></div>
+
+<h3>Stream order computation based on v.stream.order testsuite data</h3>
+
+<div class="code"><pre>
+v.stream.order input=stream_network points=stream_network_outlets \
+ output=stream_network_order threshold=25 \
+ order=strahler,shreve,drwal,scheidegger
+
+v.info stream_network_order
+v.db.select stream_network_order | less
+</pre></div>
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.stream.order.html">r.stream.order</a>
+</em>
+
+<h2>REFERENCES</h2>
+<a href="r.stream.order.html">r.stream.order</a><br>
+<a href="https://en.wikipedia.org/wiki/Depth-first_search">Depth first search at Wikipedia</a><br>
+<a href="https://en.wikipedia.org/wiki/Strahler_number">Strahler number at Wikipedia</a><br>
+
+<h2>AUTHOR</h2>
+<p>IGB-Berlin,Johannes Radinger; Implementation: Soeren Gebbert</p>
+<p>
+ This tool was developed as part of the BiodivERsA-net project 'FISHCON'
+ and has been funded by the German Federal Ministry for Education and
+ Research (grant number 01LC1205).
+</p>
+<p>Documentation of the implemented algorithms are in most parts copied from
+ r.stream.order implemented by: Jarek Jasiewicz and Markus Metz</p>
+
+<p><i>Last changed: $Date: 2013-03-27 10:11:17 +0100 (Mi, 27. Mär 2013) $</i>
+
Added: grass-addons/grass7/vector/v.stream.order/v.stream.order.py
===================================================================
--- grass-addons/grass7/vector/v.stream.order/v.stream.order.py (rev 0)
+++ grass-addons/grass7/vector/v.stream.order/v.stream.order.py 2016-04-10 12:53:24 UTC (rev 68243)
@@ -0,0 +1,580 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+############################################################################
+#
+# MODULE: v.stream.order
+# AUTHOR(S): IGB-Berlin,Johannes Radinger; Implementation: Soeren Gebbert"
+#
+# This tool was developed as part of the BiodivERsA-net project 'FISHCON'
+# and has been funded by the German Federal Ministry for Education and
+# Research (grant number 01LC1205).
+#
+# PURPOSE: Compute the stream order of stream networks stored in
+# a vector map at specific outlet vector points
+# COPYRIGHT: (C) 2015 by the GRASS Development Team
+#
+# This program is free software under the GNU General
+# Public License (>=v2). Read the file COPYING that
+# comes with GRASS for details.
+#
+#############################################################################
+
+#%module
+#% description: Compute the stream order of stream networks stored in a vector map at specific outlet vector points
+#% keyword: vector
+#%end
+#%option G_OPT_V_INPUT
+#% description: Name of the stream networks vector map
+#%end
+#%option G_OPT_V_INPUT
+#% key: points
+#% label: Name of the input vector point map
+#% description: Name of the points vector map that defines the water outlets of the stream networks
+#%end
+#%option G_OPT_V_OUTPUT
+#% label: Name of the vector output map
+#% description: The name for the stream order vector output map
+#%end
+#%option
+#% key: threshold
+#% type: double
+#% description: threshold in projection units used to search for outflow points at the stream network
+#% required : no
+#% answer: 25
+#% multiple: no
+#%end
+#%option
+#% key: order
+#% type: string
+#% description: The stream order to compute
+#% required : no
+#% answer: strahler,shreve
+#% options: strahler,shreve,scheidegger,drwal
+#% multiple: yes
+#%end
+#%option
+#% key: columns
+#% type: string
+#% description: The columns that should be copied from the input stream vector map. By default all will be copied.
+#% answer: all
+#% required : no
+#% multiple: yes
+#%end
+#%option
+#% key: recursionlimit
+#% type: integer
+#% description:The Python recursion limit that should be used (Python default is 1000)
+#% required : no
+#% answer: 10000
+#% multiple: no
+#%end
+
+import os
+import sys
+from grass.script import core as grass
+from grass.pygrass.vector import VectorTopo
+import math
+
+ORDER_STRAHLER = 1
+ORDER_SHREVE = 2
+ORDER_SCHEIDEGGER = 3
+ORDER_DRWAL = 4
+ORDER_HORTON = 5
+
+ORDER_DICT = {ORDER_STRAHLER: "strahler",
+ ORDER_SHREVE: "shreve",
+ ORDER_SCHEIDEGGER: "scheidegger",
+ ORDER_DRWAL: "drwal",
+ ORDER_HORTON: "horton"}
+
+
+class GraphEdge(object):
+ """
+ This class defines a single edge of the stream network graph
+ """
+
+ def __init__(self, id_, id_pol, start, end,
+ start_edges, end_edges,
+ reverse=False):
+ self.id = id_ # Line id
+ self.id_pol = id_pol # Polarity of line positive integer or negative integer
+ self.start = start # Start Node id
+ self.end = end # End Node id
+ self.start_edges = start_edges # A list of edge ids at the start node
+ self.end_edges = end_edges # A list of edge ids at the end node
+ self.reverse = reverse # If the edge should be reversed
+ self.stream_order = {ORDER_STRAHLER: 0,
+ ORDER_SHREVE: 0,
+ ORDER_SCHEIDEGGER: 0,
+ ORDER_DRWAL: 0} # stream_order for each algorithm
+
+ def __str__(self):
+ return "Line id: %i (%i) start node: %i " \
+ "end node: %i num start edges %i " \
+ "num end edges %i reverse: %s stream_order: %s" % (self.id, self.id_pol,
+ self.start, self.end,
+ len(self.start_edges),
+ len(self.end_edges),
+ self.reverse, str(self.stream_order))
+
+
+class GraphNode(object):
+ """
+ This class defines a single node of the node network graph
+ """
+
+ def __init__(self, id_, edge_ids):
+ self.id = id_ # Node id
+ self.edge_ids = edge_ids # Line ids
+
+ def __str__(self):
+ return "Node id: %i line ids: %s" % (self.id, self.edge_ids)
+
+
+def traverse_graph_create_stream_order(start_id,
+ edges,
+ checked_edges,
+ reversed_edges,
+ order_types=[ORDER_STRAHLER,
+ ORDER_SHREVE]):
+ """
+ Traverse the graph, reverse lines that are not in
+ the outflow direction and compute the required orders
+
+ :param start_id: The id of the edge to start the traversing from
+ :param edges: A dictionary of edge objects
+ :param checked_edges: A list with edge ids that have been checked already
+ :param reversed_edges: A list of edges that have been checked for
+ reversion and corrected if necessary
+ :param order_types: The type of the ordering scheme as a list of ints
+ * ORDER_STRAHLER = 1
+ * ORDER_SHREVE = 2
+ * ORDER_SCHEIDEGGER = 3
+ * ORDER_DRWAL = 4
+ * ORDER_HORTON = 5 -> Not correct implemented
+
+ :return:
+ """
+ current_edge = edges[start_id]
+
+ # Check for direction reversion
+ for edge_id in current_edge.start_edges:
+ if edge_id not in reversed_edges:
+ reversed_edges.append(edge_id)
+ edge = edges[edge_id]
+
+ # Reverse the edge if it is not in the outflow direction
+ if current_edge.start != edge.end:
+ start = edge.start
+ start_edges = edge.start_edges
+ edge.start = edge.end
+ edge.start_edges = edge.end_edges
+ edge.end = start
+ edge.end_edges = start_edges
+ edge.reverse = True
+
+ # Set the stream_order to one, if the edge is a leaf and return
+ if len(current_edge.start_edges) == 0:
+ for order in current_edge.stream_order:
+ current_edge.stream_order[order] = 1
+ return
+
+ stream_orders = {ORDER_STRAHLER: [],
+ ORDER_SHREVE: [],
+ ORDER_SCHEIDEGGER: [],
+ ORDER_HORTON: [],
+ ORDER_DRWAL: []}
+
+ # Traverse the graph if its not a leaf
+ for edge_id in current_edge.start_edges:
+ if edge_id not in checked_edges:
+ checked_edges.append(edge_id)
+ traverse_graph_create_stream_order(edge_id,
+ edges,
+ checked_edges,
+ reversed_edges,
+ order_types)
+
+ for order in order_types:
+ stream_orders[order].append(edges[edge_id].stream_order[order])
+
+ # Compute the stream orders
+ if ORDER_STRAHLER in order_types:
+ maximum = max(stream_orders[ORDER_STRAHLER])
+ if stream_orders[ORDER_STRAHLER].count(maximum) > 1:
+ current_edge.stream_order[ORDER_STRAHLER] = maximum + 1
+ else:
+ current_edge.stream_order[ORDER_STRAHLER] = maximum
+ if ORDER_SHREVE in order_types:
+ current_edge.stream_order[ORDER_SHREVE] = sum(stream_orders[ORDER_SHREVE])
+ if ORDER_SCHEIDEGGER in order_types:
+ current_edge.stream_order[ORDER_SCHEIDEGGER] = sum(stream_orders[ORDER_SCHEIDEGGER])
+ if ORDER_DRWAL in order_types:
+ current_edge.stream_order[ORDER_DRWAL] = sum(stream_orders[ORDER_DRWAL])
+ # Horton is wrong implemented
+ if ORDER_HORTON in order_types:
+ maximum = max(stream_orders[ORDER_HORTON])
+ current_edge.stream_order[ORDER_HORTON] = maximum + 1
+
+
+def traverse_network_create_graph(vector, start_node, graph_nodes, graph_edges):
+ """
+ Traverse a stream network vector map layer with depth-first search
+ and create a graphs structures for nodes and edges
+
+ :param vector: The opened vector input file
+ :param start_node: The start node object
+ :param graph_nodes: A dictionary of discovered nodes
+ :param graph_edges: A dictionary of Edge objects
+ :return:
+ """
+
+ # Count line ids
+ edge_ids = start_node.ilines()
+
+ # For each line at that node
+ for line_id in edge_ids:
+
+ line_id_abs = abs(line_id)
+ line = vector.read(line_id_abs)
+ nodes = line.nodes()
+
+ # If the line id is not in the edge list, create a new entry
+ if line_id_abs not in graph_edges:
+ start_edges = [abs(lid) for lid in nodes[0].ilines()]
+ end_edges = [abs(lid) for lid in nodes[1].ilines()]
+
+ start_edges.remove(line_id_abs)
+ end_edges.remove(line_id_abs)
+
+ e = GraphEdge(line_id_abs,
+ line_id,
+ nodes[0].id,
+ nodes[1].id,
+ start_edges,
+ end_edges,
+ False)
+ graph_edges[line_id_abs] = e
+
+ # For start and end node
+ for node in nodes:
+ # If the node was not yet discovered, put it
+ # into the node dict and call traverse
+ if node.id not in graph_nodes:
+ graph_nodes[node.id] = GraphNode(node.id,
+ [lid for lid in node.ilines()])
+ # Recursive call
+ traverse_network_create_graph(vector, node,
+ graph_nodes,
+ graph_edges)
+
+
+def graph_to_vector(name, mapset, graphs,
+ output, order_types,
+ outlet_cats, copy_columns):
+ """
+ Write the Graph as vector map. Attach the network id,
+ the streams orders, the reverse falg, the original
+ category and copy columns from the source stream network
+ vector map if required.
+
+ :param name: Name of the input stream vector map
+ :param mapset: Mapset name of the input stream vector map
+ :param graphs: The list of computed graphs
+ :param output: The name of the output vector map
+ :param order_types: The order algorithms
+ :param outlet_cats: Categories of the outlet points
+ :param copy_columns: The column names to be copied from the original input map
+ :return:
+ """
+ streams = VectorTopo(name=name, mapset=mapset)
+ streams.open("r")
+
+ # Specifiy all columns that should be created
+ cols = [("cat", "INTEGER PRIMARY KEY"),
+ ("outlet_cat", "INTEGER"),
+ ("network", "INTEGER"),
+ ("reversed", "INTEGER")]
+
+ for order in order_types:
+ cols.append((ORDER_DICT[order], "INTEGER"))
+
+ # Add the columns of the table from the input map
+ if copy_columns:
+ for entry in copy_columns:
+ cols.append((entry[1], entry[2]))
+
+ out_streams = VectorTopo(output)
+ grass.message(_("Writing vector map <%s>" % output))
+ out_streams.open("w", tab_cols=cols)
+
+ count = 0
+ for graph in graphs:
+ outlet_cat = outlet_cats[count]
+ count += 1
+
+ grass.message(_("Writing network %i from %i with "
+ "outlet category %i" % (count, len(graphs), outlet_cat)))
+
+ # Write each edge as line
+ for edge_id in graph:
+ edge = graph[edge_id]
+
+ line = streams.read(edge_id)
+ # Reverse the line if required
+ if edge.reverse is True:
+ line.reverse()
+
+ # Orders derived from shreve algorithm
+ if ORDER_SCHEIDEGGER in order_types:
+ edge.stream_order[ORDER_SCHEIDEGGER] *= 2
+ if ORDER_DRWAL in order_types:
+ if edge.stream_order[ORDER_DRWAL] != 0:
+ edge.stream_order[ORDER_DRWAL] = \
+ int(math.log(edge.stream_order[ORDER_DRWAL], 2) + 1)
+
+ # Create attributes
+ attrs = []
+ # Append the outlet point category
+ attrs.append(outlet_cat)
+ # Append the network id
+ attrs.append(count)
+ # The reverse flag
+ attrs.append(edge.reverse)
+ # Then the stream orders defined at the command line
+ for order in order_types:
+ val = int(edge.stream_order[order])
+ if val == 0:
+ val = None
+ attrs.append(val)
+ # Copy attributes from original streams if the table exists
+ if copy_columns:
+ for entry in copy_columns:
+ # First entry is the column index
+ attrs.append(line.attrs.values()[entry[0]])
+
+ # Write the feature
+ out_streams.write(line, cat=edge_id, attrs=attrs)
+
+ # Commit the database entries
+ out_streams.table.conn.commit()
+ # Close the input and output map
+ out_streams.close()
+ streams.close()
+
+
+def detect_compute_networks(vname, vmapset, pname, pmapset,
+ output, order, columns, threshold):
+ """
+ Detect the start edges and nodes, compute the stream networks
+ and stream orders, reverse edges and write everything into the
+ output vector map.
+
+ :param vname: Name of the input stream vector map
+ :param vmapset: Mapset name of the input stream vector map
+ :param pname: Name of the input outlet points vector map
+ :param pmapset: Mapset name of the input outlet points vector map
+ :param output: Name of the output stream vector map
+ :param order: Comma separated list of order algorithms
+ :param columns: Comma separated list of column names that should be copied to the output
+ :param threshold: The point search threshold to find start edges and nodes
+ :return:
+ """
+
+ v = VectorTopo(name=vname, mapset=vmapset)
+ p = VectorTopo(name=pname, mapset=pmapset)
+
+ v.open(mode="r")
+ p.open(mode="r")
+
+ copy_columns = None
+
+ # Check for copy columns only if the input vector map
+ # has an attribute table
+ if v.table and columns:
+
+ # These are the column names that are newly created
+ # and it must be checked if their names
+ # are exist in the input map column names
+ # that should be copied
+ # Synchronize these names with the graph_to_vector() function
+ new_column_names = order.split(",")
+ new_column_names.append("cat")
+ new_column_names.append("outlet_cat")
+ new_column_names.append("network")
+ new_column_names.append("reversed")
+ # Add the order colum names
+ new_column_names.extend(order)
+
+ # Check if all columns should be copied
+ if columns.lower() == "all":
+ columns = ",".join(v.table.columns.names())
+
+ copy_columns = []
+ for column in columns.split(","):
+ # Copy only columns that exists
+ if column in v.table.columns.names():
+ col_index = v.table.columns.names().index(column)
+ col_type = v.table.columns.types()[col_index]
+ # Rename the column if it conflicts with the
+ # order column names in the output map
+ if column in new_column_names:
+
+ # Create name suffix and make sure that the new column name
+ # does not exists
+ number = 1
+ suffix = ""
+ while True:
+ suffix = "_%i" % number
+ if column + suffix not in new_column_names and \
+ column + suffix not in columns.split(","):
+ break
+ number += 1
+
+ grass.warning(_("Column name conflict: Renaming column "
+ "<%(col)s> from input map into %(col)s%(ap)s "
+ "in output map" % {"col": column, "ap": suffix}))
+ column += suffix
+ copy_columns.append((col_index, column, col_type))
+ else:
+ v.close()
+ p.close()
+ grass.fatal(_("Column %s is not in attribute table of <%s>" % (column, vname)))
+
+ # Detect closest edges and nodes to the outflow points
+ # But why nodes, arent edges sufficient?
+ # They may be useful when detecting loops and channels
+ # in further improvements of v.stream.order.
+ start_nodes = []
+ start_node_ids = []
+ start_edges = []
+ outlet_cats = []
+
+ for point in p:
+ p_coords = point.coords()
+
+ line = v.find_by_point.geo(point=point, maxdist=float(threshold),
+ type="line")
+
+ if line:
+ n1, n2 = line.nodes()
+
+ n1_coords = n1.coords()
+ n2_coords = n2.coords()
+
+ # Compute closest node to the outflow point
+ dist1 = math.sqrt((p_coords[0] - n1_coords[0]) ** 2 +
+ (p_coords[1] - n1_coords[1]) ** 2)
+ dist2 = math.sqrt((p_coords[0] - n2_coords[0]) ** 2 +
+ (p_coords[1] - n2_coords[1]) ** 2)
+
+ if dist1 < dist2:
+ closest_node = n1
+ else:
+ closest_node = n2
+
+ grass.verbose(_("Detect edge <%i> for outflow point %s" % (line.id,
+ point.to_wkt())))
+
+ # Ignore identical starting points to avoid
+ # redundant networks in the output
+ if closest_node.id not in start_node_ids:
+ start_nodes.append(closest_node)
+ start_node_ids.append(closest_node.id)
+
+ if line.id not in start_edges:
+ start_edges.append(line.id)
+ outlet_cats.append(point.cat)
+ else:
+ grass.warning(_("Ignoring duplicated start edge"))
+
+ p.close()
+
+ if len(start_edges) == 0:
+ v.close()
+ grass.fatal(_("Unable to find start edges"))
+
+ if len(start_nodes) == 0:
+ v.close()
+ grass.fatal(_("Unable to find start nodes"))
+
+ # We create a graph representation for further computations
+ graphs = []
+
+ # Traverse each network from the outflow node on
+ for node in start_nodes:
+ graph_nodes = {}
+ graph_edges = {}
+ graph_nodes[node.id] = GraphNode(node.id, [lid for lid in node.ilines()])
+ traverse_network_create_graph(v, node, graph_nodes, graph_edges)
+ # For now we only use the edges graph
+ graphs.append(graph_edges)
+
+ # Close the vector map, since we have our own graph representation
+ v.close()
+
+ # Set stream order types
+ order_types = []
+
+ if order.find("strahler") >= 0:
+ order_types.append(ORDER_STRAHLER)
+ if order.find("scheidegger") >= 0:
+ order_types.append(ORDER_SCHEIDEGGER)
+ if order.find("drwal") >= 0:
+ order_types.append(ORDER_DRWAL)
+ if order.find("horton") >= 0:
+ order_types.append(ORDER_HORTON)
+ if order.find("shreve") >= 0:
+ order_types.append(ORDER_SHREVE)
+
+ # Compute the stream orders
+ for i in xrange(len(start_edges)):
+ edge_id = start_edges[i]
+ checked_edges = []
+ reversed_edges = []
+ traverse_graph_create_stream_order(edge_id, graphs[i],
+ checked_edges,
+ reversed_edges,
+ order_types)
+
+ # Write the graphs as vector map
+ graph_to_vector(vname, vmapset, graphs,
+ output, order_types,
+ outlet_cats, copy_columns)
+
+
+def main():
+ input = options["input"]
+ points = options["points"]
+ output = options["output"]
+ order = options["order"]
+ threshold = options["threshold"]
+ columns = options["columns"]
+ recursionlimit = options["recursionlimit"]
+
+ # We are using a recursive tree traversing algorithm, that may exceed
+ # the 1000 recursion length for huge networks.
+ # The default is 10000 in the option section
+ if int(recursionlimit) < 1000:
+ grass.fatal(_("The Python recursion limit should be equal or larger than 1000"))
+
+ sys.setrecursionlimit(int(recursionlimit))
+
+ # Check map names for mapsets
+ vname = input
+ vmapset = ""
+ if "@" in input:
+ vname, vmapset = input.split("@")
+
+ pname = points
+ pmapset = ""
+ if "@" in points:
+ pname, pmapset = points.split("@")
+
+ detect_compute_networks(vname, vmapset, pname, pmapset, output, order,
+ columns, threshold)
+
+
+if __name__ == "__main__":
+ options, flags = grass.parser()
+ main()
More information about the grass-commit
mailing list