Revision: 6566
          http://sourceforge.net/p/jump-pilot/code/6566
Author:   michaudm
Date:     2020-10-03 17:59:16 +0000 (Sat, 03 Oct 2020)
Log Message:
-----------
Add Shreve, Horton and Hack Orders to Stream Order plugin

Modified Paths:
--------------
    plug-ins/GraphToolboxPlugin/trunk/build.xml
    plug-ins/GraphToolboxPlugin/trunk/doc/GraphToolboxExtension4OJ.odt
    plug-ins/GraphToolboxPlugin/trunk/doc/GraphToolboxExtension4OJ_fr.odt
    
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/GraphExtension.java
    
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/StrahlerNumberPlugIn.java
    
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph.properties
    
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_cz.properties
    
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_fi.properties
    
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_fr.properties
    
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_it.properties

Added Paths:
-----------
    plug-ins/GraphToolboxPlugin/trunk/lib/jump-jgrapht-0.7.1.jar

Removed Paths:
-------------
    plug-ins/GraphToolboxPlugin/trunk/lib/jump-jgrapht-0.7.jar

Modified: plug-ins/GraphToolboxPlugin/trunk/build.xml
===================================================================
--- plug-ins/GraphToolboxPlugin/trunk/build.xml 2020-10-02 14:29:59 UTC (rev 
6565)
+++ plug-ins/GraphToolboxPlugin/trunk/build.xml 2020-10-03 17:59:16 UTC (rev 
6566)
@@ -17,7 +17,7 @@
     <property name="dist"    value="dist" />
     <property name="javadoc" value="javadoc" />
 
-    <property name="version" value="0.7.0" />
+    <property name="version" value="0.8.0" />
     
     <!-- =================================================================== 
-->
     <!-- Defines the classpath used for compilation and test.                
-->

Modified: plug-ins/GraphToolboxPlugin/trunk/doc/GraphToolboxExtension4OJ.odt
===================================================================
(Binary files differ)

Modified: plug-ins/GraphToolboxPlugin/trunk/doc/GraphToolboxExtension4OJ_fr.odt
===================================================================
(Binary files differ)

Added: plug-ins/GraphToolboxPlugin/trunk/lib/jump-jgrapht-0.7.1.jar
===================================================================
(Binary files differ)

Index: plug-ins/GraphToolboxPlugin/trunk/lib/jump-jgrapht-0.7.1.jar
===================================================================
--- plug-ins/GraphToolboxPlugin/trunk/lib/jump-jgrapht-0.7.1.jar        
2020-10-02 14:29:59 UTC (rev 6565)
+++ plug-ins/GraphToolboxPlugin/trunk/lib/jump-jgrapht-0.7.1.jar        
2020-10-03 17:59:16 UTC (rev 6566)

Property changes on: 
plug-ins/GraphToolboxPlugin/trunk/lib/jump-jgrapht-0.7.1.jar
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Deleted: plug-ins/GraphToolboxPlugin/trunk/lib/jump-jgrapht-0.7.jar
===================================================================
(Binary files differ)

Modified: 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/GraphExtension.java
===================================================================
--- 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/GraphExtension.java
     2020-10-02 14:29:59 UTC (rev 6565)
+++ 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/GraphExtension.java
     2020-10-03 17:59:16 UTC (rev 6566)
@@ -35,8 +35,9 @@
  * <li>CycleFinderPlugIn : computes a graph from a linear network and find 
base cycles</li>
  * </ul>
  * @author Micha&euml;l Michaud
- * @version 0.7.0 (2020-09-18)
+ * @version 0.8.0 (2020-10-03)
  */
+//version 0.8.0 (2020-10-03) Add Shreve, Horton and Hack Orders to Stream 
Order plugin
 //version 0.7.0 (2020-09-23) Make strahlerNumber plugin more memory friendly 
and way faster
 //version 0.6.3 (2019-06-24) SkeletonPlugIn : improve meanWidth calculation
 //version 0.6.2 (2019-05-22) fix bug in SkeletonPlugIn : incorrect 
relativeMinForkLength
@@ -64,7 +65,7 @@
     }
 
     public String getVersion() {
-        return "0.7.0 (2020-09-23)";
+        return "0.8.0 (2020-10-03)";
     }
 
     public void configure(PlugInContext context) throws Exception {

Modified: 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/StrahlerNumberPlugIn.java
===================================================================
--- 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/StrahlerNumberPlugIn.java
       2020-10-02 14:29:59 UTC (rev 6565)
+++ 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/StrahlerNumberPlugIn.java
       2020-10-03 17:59:16 UTC (rev 6566)
@@ -8,6 +8,7 @@
 import com.vividsolutions.jump.workbench.model.Layer;
 import com.vividsolutions.jump.workbench.model.StandardCategoryNames;
 import com.vividsolutions.jump.workbench.plugin.*;
+import com.vividsolutions.jump.workbench.ui.AttributeTypeFilter;
 import com.vividsolutions.jump.workbench.ui.GUIUtil;
 import com.vividsolutions.jump.workbench.ui.MenuNames;
 import com.vividsolutions.jump.workbench.ui.MultiInputDialog;
@@ -19,6 +20,8 @@
 
 import javax.swing.*;
 import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.util.*;
 
 /**
@@ -29,16 +32,44 @@
 
     private static String LAYER;
 
-    private static String STRAHLER_NUMBERS;
+    private static String STREAM_ORDER;
     private static String GRAPH_COMPUTATION;
     private static String OLD_ALGO;
+    private static String LENGTH_ATTRIBUTE;
 
-    private static final String STREAM_ORDER    = "StreamOrder";
-    private static final String SEGMENT_ORIGIN  = "SegmentOrig";
+    private static final String STRAHLER          = "Strahler";
+    private static String STRAHLER_TT;
+    private static final String SEGMENT_ORIGIN    = "SegmentOrig";
+    private static final String SHREVE            = "Shreve";
+    private static String SHREVE_TT;
 
+    private static String METRICS;
+    private static final String FLOW_ACC          = "FlowAcc";
+    private static final String MAX_DIST          = "MaxDist";
+    private static final String HORTON            = "Horton";
+    private static String HORTON_TT;
+    private static final String HACK              = "Hack";
+    private static String HACK_TT;
+    private static final String HACK_DIST_ORDER   = "HackDistO";
+    private static final String HACK_DIST         = "HackDist";
+    private static final String HACK_FLOW_ORDER   = "HackFlowO";
+    private static final String HACK_FLOW         = "HackFlow";
+    private static final String HACK_DF_ORDER     = "HackDFO";
+    private static final String HACK_DF           = "HackDF";
+    private static final String MOUTH_DISTANCE    = "MouthDist";
+
     Layer layer;
     boolean old_algo = false;
+    boolean shreve   = false;
 
+    boolean metrics  = false;
+    boolean horton   = false;
+    boolean hack     = false;
+    String lengthAttribute;
+    int lengthAttributeIndex;
+    boolean lengthAttributeIsGeometry;
+
+
     public String getName() {return "Graph nodes PlugIn";}
 
     public void initialize(final PlugInContext context) throws Exception {
@@ -47,12 +78,18 @@
 
         LAYER                   = I18N.get("ui.GenericNames.LAYER");
         GRAPH_COMPUTATION       = I18NPlug.getI18N("Graph-computation");
-        STRAHLER_NUMBERS        = 
I18NPlug.getI18N("StrahlerNumberPlugIn.strahler-numbers");
+        STREAM_ORDER            = 
I18NPlug.getI18N("StrahlerNumberPlugIn.stream-order");
+        STRAHLER_TT             = 
I18NPlug.getI18N("StrahlerNumberPlugIn.strahler-tt");
+        SHREVE_TT               = 
I18NPlug.getI18N("StrahlerNumberPlugIn.shreve-tt");
         OLD_ALGO                = 
I18NPlug.getI18N("StrahlerNumberPlugIn.old-algorithm");
+        METRICS                 = 
I18NPlug.getI18N("StrahlerNumberPlugIn.metrics");
+        LENGTH_ATTRIBUTE        = 
I18NPlug.getI18N("StrahlerNumberPlugIn.length-attribute");
+        HORTON_TT               = 
I18NPlug.getI18N("StrahlerNumberPlugIn.horton-tt");
+        HACK_TT                 = 
I18NPlug.getI18N("StrahlerNumberPlugIn.hack-tt");
 
         context.getFeatureInstaller().addMainMenuPlugin(
                 this, new String[]{MenuNames.PLUGINS, GRAPH},
-                STRAHLER_NUMBERS + "...",
+                STREAM_ORDER + "...",
                 false, null, new MultiEnableCheck()
                         
.add(context.getCheckFactory().createTaskWindowMustBeActiveCheck())
                         
.add(context.getCheckFactory().createAtLeastNLayersMustExistCheck(1)));
@@ -60,19 +97,23 @@
 
     @Override
     public boolean execute(PlugInContext context) throws Exception {
-        final MultiInputDialog dialog = new MultiInputDialog(
-                context.getWorkbenchFrame(), STRAHLER_NUMBERS, true);
-        dialog.setSideBarImage(new 
ImageIcon(this.getClass().getResource("StrahlerNumber.png")));
-        
dialog.setSideBarDescription(I18NPlug.getI18N("StrahlerNumberPlugIn.description"));
-        dialog.addLayerComboBox(LAYER, context.getCandidateLayer(0), null, 
context.getLayerManager());
-        dialog.addCheckBox(OLD_ALGO, old_algo);
+        final MultiInputDialog dialog = initDialog(context);
 
-        GUIUtil.centreOnWindow(dialog);
-        dialog.setPreferredSize(new Dimension(400,480));
+                GUIUtil.centreOnWindow(dialog);
+        dialog.setPreferredSize(new Dimension(480,480));
         dialog.setVisible(true);
         if (dialog.wasOKPressed()) {
             layer = dialog.getLayer(LAYER);
             old_algo = dialog.getBoolean(OLD_ALGO);
+            shreve = dialog.getBoolean(SHREVE);
+            metrics = dialog.getBoolean(METRICS);
+            lengthAttribute = dialog.getText(LENGTH_ATTRIBUTE);
+            lengthAttributeIndex = layer.getFeatureCollectionWrapper()
+                    .getFeatureSchema().getAttributeIndex(lengthAttribute);
+            lengthAttributeIsGeometry = lengthAttributeIndex ==
+                    
layer.getFeatureCollectionWrapper().getFeatureSchema().getGeometryIndex();
+            hack = dialog.getBoolean(HACK);
+            horton = dialog.getBoolean(HORTON);
             return true;
         }
         else return false;
@@ -86,8 +127,21 @@
 
         // Creates the schema for the output dataset (nodes)
         final FeatureSchema newSchema = sourceFC.getFeatureSchema().clone();
-        newSchema.addAttribute(STREAM_ORDER, AttributeType.INTEGER);
+        newSchema.addAttribute(STRAHLER, AttributeType.INTEGER);
         newSchema.addAttribute(SEGMENT_ORIGIN, AttributeType.OBJECT);
+        if (shreve) newSchema.addAttribute(SHREVE, AttributeType.DOUBLE);
+        if (metrics) newSchema.addAttribute(MAX_DIST, AttributeType.DOUBLE);
+        if (metrics) newSchema.addAttribute(FLOW_ACC, AttributeType.DOUBLE);
+        if (hack) {
+            newSchema.addAttribute(HACK_DIST_ORDER, AttributeType.INTEGER);
+            newSchema.addAttribute(HACK_DIST, AttributeType.DOUBLE);
+            newSchema.addAttribute(HACK_FLOW_ORDER, AttributeType.INTEGER);
+            newSchema.addAttribute(HACK_FLOW, AttributeType.DOUBLE);
+            newSchema.addAttribute(MOUTH_DISTANCE, AttributeType.DOUBLE);
+            newSchema.addAttribute(HACK_DF_ORDER, AttributeType.INTEGER);
+            newSchema.addAttribute(HACK_DF, AttributeType.DOUBLE);
+        }
+        if (horton) newSchema.addAttribute(HORTON, AttributeType.INTEGER);
         FeatureCollection resultFC = new FeatureDataset(newSchema);
         for (Object o : sourceFC.getFeatures()) {
             Feature f = (Feature)o;
@@ -105,18 +159,41 @@
         int count = 0;
         int total = resultFC.size();
         for (FeatureAsEdge arc : graph.edgeSet()) {
-            if (arc.getAttribute(STREAM_ORDER) != null) continue;
-            if (old_algo) computeOldStreamOrder(graph, arc);
-            else computeNewStreamOrder(graph, arc);
-            monitor.report(count++, total, " features processed");
+            if (arc.getAttribute(STRAHLER) != null) continue;
+            if (old_algo) computeLegacyStrahlerOrder(graph, arc);
+            else computeNewStrahlerOrder(graph, arc);
+            monitor.report(count++, total, " features processed (Strahler)");
         }
         // Change -1 (cycles or cycle successors) to null
         for (FeatureAsEdge arc : graph.edgeSet()) {
-            Object order = arc.getAttribute(STREAM_ORDER);
+            Object order = arc.getAttribute(STRAHLER);
             if (order != null && (Integer)order == -1) {
-                arc.setAttribute(STREAM_ORDER,null);
+                arc.setAttribute(STRAHLER,null);
             }
         }
+        if (metrics) {
+            int maxDistIdx = newSchema.getAttributeIndex(MAX_DIST);
+            int flowAccIdx = newSchema.getAttributeIndex(FLOW_ACC);
+            for (FeatureAsEdge arc : graph.edgeSet()) {
+                if (arc.getAttribute(MAX_DIST) != null) continue;
+                computeMaxLengthAndFlowAcc(graph, arc, maxDistIdx, flowAccIdx);
+                monitor.report(count++, total, " features processed (max dist 
/flow accumulation)");
+            }
+            if (horton) {
+                for (FeatureAsEdge arc : graph.edgeSet()) {
+                    if (arc.getAttribute(HORTON) != null) continue;
+                    computeHortonStreamOrder(graph, arc);
+                    monitor.report(count++, total, " features processed 
(Horton)");
+                }
+            }
+            if (hack) {
+                for (FeatureAsEdge arc : graph.edgeSet()) {
+                    if (arc.getAttribute(HACK_DIST_ORDER) != null) continue;
+                    computeHackStreamOrder(graph, arc);
+                    monitor.report(count++, total, " features processed 
(Hack)");
+                }
+            }
+        }
 
         context.getLayerManager().addLayer(StandardCategoryNames.RESULT, 
layer.getName()+"-strahler",resultFC);
         Layer resultLayer = context.getLayerManager().getLayer(layer.getName() 
+ "-strahler");
@@ -142,7 +219,7 @@
      * @param graph
      * @param arc
      */
-    private void 
computeOldStreamOrder(DirectedWeightedPseudograph<INode,FeatureAsEdge> graph,
+    private void 
computeLegacyStrahlerOrder(DirectedWeightedPseudograph<INode,FeatureAsEdge> 
graph,
                                    FeatureAsEdge arc) {
 
         int maxOrder = 0;
@@ -149,7 +226,7 @@
         int occ = 0;
         FeatureAsEdge maxUpstream = null;
         for (FeatureAsEdge upstream : 
graph.incomingEdgesOf(graph.getEdgeSource(arc))) {
-            Object att = upstream.getAttribute(STREAM_ORDER);
+            Object att = upstream.getAttribute(STRAHLER);
             // Process current stream only if all upstreams are already 
processed
             if (att == null) return;
             int upstreamOrder = (Integer)att;
@@ -172,12 +249,16 @@
         }
         // Head water of a stream (edge without predecessor) has order 1
         if (maxOrder == 0) {
-            arc.setAttribute(STREAM_ORDER, 1);
+            arc.setAttribute(STRAHLER, 1);
+            if (shreve) arc.setAttribute(SHREVE, 1.0);
+            //if (metrics) arc.setAttribute(FLOW_ACC, getLength(arc));
         }
         else {
             // Stream order of the current edge is incremented if it has 2 or 
more
             // predecessors = maxOrder
-            arc.setAttribute(STREAM_ORDER, occ>1?maxOrder+1:maxOrder);
+            arc.setAttribute(STRAHLER, occ>1?maxOrder+1:maxOrder);
+            if (shreve) arc.setAttribute(SHREVE, calculateShreveNumber(graph, 
arc));
+            //if (metrics) arc.setAttribute(FLOW_ACC, 
calculateFlowAccumulation(graph, arc));
         }
         // Try to compute stream order recursively on all downstream edges
         Set<FeatureAsEdge> downStreams = 
graph.outgoingEdgesOf(graph.getEdgeTarget(arc));
@@ -184,12 +265,24 @@
 
         for (FeatureAsEdge downStream : downStreams) {
             // In case of anastomosis, compute the downstream edge only once
-            if (downStream.getAttribute(STREAM_ORDER) == null) {
-                computeOldStreamOrder(graph, downStream);
+            if (downStream.getAttribute(STRAHLER) == null) {
+                computeLegacyStrahlerOrder(graph, downStream);
             }
         }
     }
 
+    private double 
calculateShreveNumber(DirectedWeightedPseudograph<INode,FeatureAsEdge> graph,
+                                  FeatureAsEdge arc) {
+        INode n = graph.getEdgeSource(arc);
+        double s = 0.0;
+        int attIdx = arc.getSchema().getAttributeIndex(SHREVE);
+        for (FeatureAsEdge e : graph.incomingEdgesOf(n)) {
+            s += e.getDouble(attIdx);
+        }
+        return s / graph.outDegreeOf(graph.getEdgeSource(arc));
+    }
+
+
     private Set<Integer> 
getAncestors(DirectedWeightedPseudograph<INode,FeatureAsEdge> graph,
                                    FeatureAsEdge arc, Set<Integer> ancestors) {
         for (FeatureAsEdge e : 
graph.incomingEdgesOf(graph.getEdgeSource(arc))) {
@@ -214,18 +307,18 @@
     // A FAST RECURSIVE GIS ALGORITHM FOR COMPUTING STRAHLER STREAM ORDER
     // IN BRAIDED AND NON BRAIDED NETWORKS
     // Alexander Gleyzer, Michael Denisyuk, Alon Rimmer, and Yigal Salingar 
(2004)
-    private void 
computeNewStreamOrder(DirectedWeightedPseudograph<INode,FeatureAsEdge> graph,
+    private void 
computeNewStrahlerOrder(DirectedWeightedPseudograph<INode,FeatureAsEdge> graph,
                                      FeatureAsEdge arc) {
 
-        Object streamOrder = arc.getAttribute(STREAM_ORDER);
+        Object strahlerOrder = arc.getAttribute(STRAHLER);
         // If arc already has a positive stream order, don't process it again
         // If its stream-order = -1, it means it belongs to a cycle, or it 
belongs
         // to an ancestor and has been pre-set to -1 to detect cycles
         // In all of these case, we don't want to process it
-        if (streamOrder != null) return;
+        if (strahlerOrder != null) return;
         // Flag current edge to be able to identify cycles while exploring 
ancestors
         // recursively
-        arc.setAttribute(STREAM_ORDER, -1);
+        arc.setAttribute(STRAHLER, -1);
 
         // Stream order of the current edge has not yet been computed.
         // Compute predecessors stream order first (recursion)
@@ -233,11 +326,11 @@
         boolean cycle = false;
         for (FeatureAsEdge upStream : upStreams) {
             // Visit/compute ancestors recursively
-            computeNewStreamOrder(graph, upStream);
+            computeNewStrahlerOrder(graph, upStream);
             // Post order : check that current stream is not part of a cycle
             // if upstream == -1, it means it has already been initialized in 
the context
             // of this recursive process (cycle)
-            Object upStreamOrder = upStream.getAttribute(STREAM_ORDER);
+            Object upStreamOrder = upStream.getAttribute(STRAHLER);
             assert upStreamOrder != null; // stream order is initialized to -1 
in pre-order
             if ((Integer)upStreamOrder == -1) {
                 cycle = true;
@@ -254,7 +347,7 @@
         INode maxOrderOrigin = null;
         int occ = 0;
         for (FeatureAsEdge upstream : 
graph.incomingEdgesOf(graph.getEdgeSource(arc))) {
-            Object att1 = upstream.getAttribute(STREAM_ORDER);
+            Object att1 = upstream.getAttribute(STRAHLER);
             assert att1 != null;
 
             int upstreamOrder = (Integer)att1;
@@ -274,22 +367,306 @@
         }
         // Set the stream order and segment origin of the current edge
         if (maxOrder == 0) {
-            arc.setAttribute(STREAM_ORDER, 1);
+            arc.setAttribute(STRAHLER, 1);
             arc.setAttribute(SEGMENT_ORIGIN, graph.getEdgeSource(arc));
+            if (shreve) arc.setAttribute(SHREVE, 1.0);
+            //if (flowAcc) arc.setAttribute(FLOW_ACC, getLength(arc));
         }
         else if (occ > 1) {
-            arc.setAttribute(STREAM_ORDER, maxOrder+1);
+            arc.setAttribute(STRAHLER, maxOrder+1);
             arc.setAttribute(SEGMENT_ORIGIN, graph.getEdgeSource(arc));
+            if (shreve) arc.setAttribute(SHREVE, calculateShreveNumber(graph, 
arc));
+            //if (flowAcc) arc.setAttribute(FLOW_ACC, 
calculateFlowAccumulation(graph, arc));
         }
         else {
-            arc.setAttribute(STREAM_ORDER, maxOrder);
+            arc.setAttribute(STRAHLER, maxOrder);
             arc.setAttribute(SEGMENT_ORIGIN, maxOrderOrigin);
+            if (shreve) arc.setAttribute(SHREVE, calculateShreveNumber(graph, 
arc));
+            //if (flowAcc) arc.setAttribute(FLOW_ACC, 
calculateFlowAccumulation(graph, arc));
         }
 
     }
 
+    private void 
computeMaxLengthAndFlowAcc(DirectedWeightedPseudograph<INode,FeatureAsEdge> 
graph,
+                                            FeatureAsEdge arc, int maxDistIdx, 
int flowAccIdx) {
+        // Interrupt infinite recursion in case of cycle
+        if (arc.getAttribute(MAX_DIST) != null) return;
+        arc.setAttribute(MAX_DIST, getLength(arc));
+        arc.setAttribute(FLOW_ACC, getLength(arc));
+        // Compute predecessors stream order first (recursion)
+        Set<FeatureAsEdge> upStreams = 
graph.incomingEdgesOf(graph.getEdgeSource(arc));
+        // Visit/compute ancestors recursively
+        for (FeatureAsEdge upStream : upStreams) {
+            computeMaxLengthAndFlowAcc(graph, upStream, maxDistIdx, 
flowAccIdx);
+        }
+        // We are now in the normal situation of an edge whith all its 
ancestors computed
+        double maxMaxDist = 0;
+        double maxFlowAcc = 0;
+        for (FeatureAsEdge upstream : 
graph.incomingEdgesOf(graph.getEdgeSource(arc))) {
+            double maxDist = upstream.getDouble(maxDistIdx);
+            double flowAcc = upstream.getDouble(flowAccIdx);
+            if (maxDist > maxMaxDist) maxMaxDist = maxDist;
+            if (flowAcc > maxFlowAcc) maxFlowAcc = flowAcc;
+        }
+        arc.setAttribute(MAX_DIST, arc.getDouble(maxDistIdx) + maxMaxDist);
+        arc.setAttribute(FLOW_ACC, calculateFlowAccumulation(graph, arc));
+    }
 
+    private double getLength(FeatureAsEdge arc) {
+        return lengthAttributeIsGeometry ?
+                arc.getGeometry().getLength() : 
arc.getDouble(lengthAttributeIndex);
+    }
 
+    private double 
calculateFlowAccumulation(DirectedWeightedPseudograph<INode,FeatureAsEdge> 
graph,
+                                             FeatureAsEdge arc) {
+        INode n = graph.getEdgeSource(arc);
+        double s = 0.0;
+        for (FeatureAsEdge e : graph.incomingEdgesOf(n)) {
+            s += (Double)e.getAttribute(FLOW_ACC);
+        }
+        return getLength(arc) +
+                s / graph.outDegreeOf(graph.getEdgeSource(arc));
+    }
+
+    private void 
computeHortonStreamOrder(DirectedWeightedPseudograph<INode,FeatureAsEdge> graph,
+                                       FeatureAsEdge arc) {
+        // Horton's computation needs Strahler order
+        if (arc.getAttribute(STRAHLER) == null) return;
+        if (graph.outDegreeOf(graph.getEdgeTarget(arc)) == 0) {
+            arc.setAttribute(HORTON, arc.getAttribute(STRAHLER));
+        } else {
+            Set<FeatureAsEdge> downStreams = 
graph.outgoingEdgesOf(graph.getEdgeTarget(arc));
+            int maxDownStreamOrder = 0;
+            for (FeatureAsEdge d : downStreams) {
+                // Calculate Horton order of successors first
+                if (d.getAttribute(HORTON) == null) {
+                    computeHortonStreamOrder(graph, d);
+                }
+                Object h = d.getAttribute(HORTON);
+                if (h == null) continue;
+                if ((Integer)h > maxDownStreamOrder) maxDownStreamOrder = 
(Integer)h;
+            }
+            // When Horton order of all successors have been calculated,
+            // iterate through all tributaries flowing this arc's successors
+            // to find the main one
+            int maxOrder = 0;
+            double maxFlow = 0.0;
+            FeatureAsEdge maxEdge = null;
+            // Compare all incoming edges arriving at the same node as arc
+            Set<FeatureAsEdge> upStreams = 
graph.incomingEdgesOf(graph.getEdgeTarget(arc));
+            for (FeatureAsEdge e : upStreams) {
+                if (e.getAttribute(STRAHLER) == null) continue;
+                int order = (Integer)e.getAttribute(STRAHLER);
+                double flow = (Double)e.getAttribute(FLOW_ACC);
+                if (order > maxOrder || (order == maxOrder && flow > maxFlow)) 
{
+                    maxOrder = order;
+                    maxFlow = flow;
+                    maxEdge = e;
+                }
+            }
+            for (FeatureAsEdge e : upStreams) {
+                if (e == maxEdge) {
+                    e.setAttribute(HORTON, maxDownStreamOrder);
+                } else {
+                    e.setAttribute(HORTON, e.getAttribute(STRAHLER));
+                }
+            }
+        }
+    }
+
+    private void 
computeHackStreamOrder(DirectedWeightedPseudograph<INode,FeatureAsEdge> graph,
+                                          FeatureAsEdge arc) {
+        arc.setAttribute(HACK_DIST_ORDER, Integer.MAX_VALUE);
+        arc.setAttribute(HACK_FLOW_ORDER, Integer.MAX_VALUE);
+        if (graph.outDegreeOf(graph.getEdgeTarget(arc)) == 0) {
+            arc.setAttribute(HACK_DIST_ORDER, 1);
+            arc.setAttribute(HACK_FLOW_ORDER, 1);
+            arc.setAttribute(HACK_DF_ORDER, 1);
+            arc.setAttribute(HACK_DIST, arc.getAttribute(MAX_DIST));
+            arc.setAttribute(HACK_FLOW, arc.getAttribute(FLOW_ACC));
+            arc.setAttribute(HACK_DF, 
(double)arc.getAttribute(FLOW_ACC)*(double)arc.getAttribute(MAX_DIST));
+            arc.setAttribute(MOUTH_DISTANCE, getLength(arc));
+        } else {
+            Set<FeatureAsEdge> downStreams = 
graph.outgoingEdgesOf(graph.getEdgeTarget(arc));
+            boolean cycle = false;
+            for (FeatureAsEdge d : downStreams) {
+                // Calculate Hack order of successors first
+                if (d.getAttribute(HACK_DIST_ORDER) == null || 
d.getAttribute(HACK_FLOW_ORDER) == null) {
+                    computeHackStreamOrder(graph, d);
+                }
+                // cycle detection
+                Object hdo = d.getAttribute(HACK_DIST_ORDER);
+                Object hfo = d.getAttribute(HACK_FLOW_ORDER);
+                assert hdo != null && hfo != null;
+                if ((Integer)hdo == -1 || (Integer)hfo == -1) {
+                    cycle = true;
+                }
+
+            }
+            FeatureAsEdge mainDownStreamD = null;
+            FeatureAsEdge mainDownStreamF = null;
+            FeatureAsEdge mainDownStreamDF = null;
+            double maxMouthDist = 0.0;
+            // In case of division, choose the downstream which is the 
farthest from the river mouth
+            // to avoid little forks which do not throw into the sea
+            double maxProductD = 0.0;
+            double maxProductF = 0.0;
+            double maxProductDF = 0.0;
+            for (FeatureAsEdge d : downStreams) {
+                //Object hackD = d.getAttribute(HACK_DIST_ORDER);
+                //Object hackF = d.getAttribute(HACK_FLOW_ORDER);
+                Object mouthDist = d.getAttribute(MOUTH_DISTANCE);
+                Object hackDistOrder = d.getAttribute(HACK_DIST_ORDER);
+                if (hackDistOrder != null && mouthDist != null  &&
+                        (double)mouthDist / (int)hackDistOrder > maxProductD) {
+                    maxProductD = (double)mouthDist / (int)hackDistOrder;
+                    mainDownStreamD = d;
+                }
+                Object hackFlowOrder = d.getAttribute(HACK_FLOW_ORDER);
+                if (hackFlowOrder != null && mouthDist != null &&
+                        (double)mouthDist / (int)hackFlowOrder > maxProductF) {
+                    maxProductF = (double)mouthDist / (int)hackFlowOrder;
+                    mainDownStreamF = d;
+                }
+                Object hackDFOrder = d.getAttribute(HACK_DF_ORDER);
+                if (hackDFOrder != null && mouthDist != null &&
+                        (double)mouthDist / (int)hackDFOrder > maxProductDF) {
+                    maxProductDF = (double)mouthDist / (int)hackDFOrder;
+                    mainDownStreamDF = d;
+                }
+                if (mouthDist != null && (Double)mouthDist > maxMouthDist) {
+                    maxMouthDist = (Double) d.getAttribute(MOUTH_DISTANCE);
+                }
+            }
+            arc.setAttribute(MOUTH_DISTANCE, getLength(arc) + maxMouthDist);
+            int downStreamHackDistanceOrder = 1;
+            double downStreamDistance = 0.0;
+            if (mainDownStreamD != null && 
mainDownStreamD.getAttribute(HACK_DIST_ORDER) != null) {
+                downStreamHackDistanceOrder = 
(int)mainDownStreamD.getAttribute(HACK_DIST_ORDER);
+                downStreamDistance = 
(double)mainDownStreamD.getAttribute(HACK_DIST);
+            }
+            int downStreamHackFlowOrder = 1;
+            double downStreamFlow = 0.0;
+            if (mainDownStreamF != null && 
mainDownStreamF.getAttribute(HACK_FLOW_ORDER) != null) {
+                downStreamHackFlowOrder = 
(int)mainDownStreamF.getAttribute(HACK_FLOW_ORDER);
+                downStreamFlow = 
(double)mainDownStreamF.getAttribute(HACK_FLOW);
+            }
+            int downStreamHackDFOrder = 1;
+            double downStreamDF = 0.0;
+            if (mainDownStreamDF != null && 
mainDownStreamDF.getAttribute(HACK_DF_ORDER) != null) {
+                downStreamHackDFOrder = 
(int)mainDownStreamDF.getAttribute(HACK_DF_ORDER);
+                downStreamDF = (double)mainDownStreamDF.getAttribute(HACK_DF);
+            }
+            //int downStreamHackD = 1;
+            //int downStreamHackF = 1;
+            //Object downStreamDist = arc.getAttribute(MAX_DIST);
+            //Object downStreamFlow = arc.getAttribute(FLOW_ACC);
+            //if (mainDownStreamD != null) {
+            //    downStreamHackD = 
(int)mainDownStreamD.getAttribute(HACK_DIST_ORDER);
+            //    downStreamHackF = 
(int)mainDownStreamF.getAttribute(HACK_FLOW_ORDER);
+            //    downStreamDist = mainDownStreamD.getAttribute(HACK_DIST);
+            //    downStreamFlow = mainDownStreamF.getAttribute(HACK_FLOW);
+            //}
+            // Process cycles as a stream start
+            //if (minHackD == Integer.MAX_VALUE) {
+            //    minHackD = 1;
+            //    downStreamDist = (Double)arc.getAttribute(MAX_DIST);
+            //}
+            //if (minHackF == Integer.MAX_VALUE) {
+            //    minHackF = 1;
+            //    downStreamFlow = (Double)arc.getAttribute(FLOW_ACC);
+            //}
+
+            //maxDownStreamMouthDist = 
(Double)arc.getAttribute(MOUTH_DISTANCE);
+
+            // When Horton order of all successors have been calculated,
+            // search the main tributary
+            double maxFlow = 0.0;
+            double maxDist = 0.0;
+            double maxDF = 0.0;
+            FeatureAsEdge maxFlowEdge = null;
+            FeatureAsEdge maxDistEdge = null;
+            FeatureAsEdge maxDFEdge = null;
+            // Compare all incoming edges arriving at the same node as arc
+            Set<FeatureAsEdge> upStreams = 
graph.incomingEdgesOf(graph.getEdgeTarget(arc));
+            for (FeatureAsEdge e : upStreams) {
+                double flow = (Double)e.getAttribute(FLOW_ACC);
+                double dist = (Double)e.getAttribute(MAX_DIST);
+                double df = 
(Double)e.getAttribute(MAX_DIST)*(Double)e.getAttribute(FLOW_ACC);
+                if (flow > maxFlow) {
+                    maxFlow = flow;
+                    maxFlowEdge = e;
+                }
+                if (dist > maxDist) {
+                    maxDist = dist;
+                    maxDistEdge = e;
+                }
+                if (df > maxDF) {
+                    maxDF = df;
+                    maxDFEdge = e;
+                }
+            }
+            for (FeatureAsEdge e : upStreams) {
+                if (e == maxFlowEdge) {
+                    e.setAttribute(HACK_FLOW_ORDER, downStreamHackFlowOrder);
+                    e.setAttribute(HACK_FLOW, downStreamFlow);
+                } else {
+                    e.setAttribute(HACK_FLOW_ORDER, downStreamHackFlowOrder + 
1);
+                    e.setAttribute(HACK_FLOW, e.getAttribute(FLOW_ACC));
+                }
+                if (e == maxDistEdge) {
+                    e.setAttribute(HACK_DIST_ORDER, 
downStreamHackDistanceOrder);
+                    e.setAttribute(HACK_DIST, downStreamDistance);
+                } else {
+                    e.setAttribute(HACK_DIST_ORDER, 
downStreamHackDistanceOrder + 1);
+                    e.setAttribute(HACK_DIST, e.getAttribute(MAX_DIST));
+                }
+                if (e == maxDFEdge) {
+                    e.setAttribute(HACK_DF_ORDER, downStreamHackDFOrder);
+                    e.setAttribute(HACK_DF, downStreamDF);
+                } else {
+                    e.setAttribute(HACK_DF_ORDER, downStreamHackDFOrder + 1);
+                    e.setAttribute(HACK_DF, 
(double)e.getAttribute(MAX_DIST)*(double)e.getAttribute(FLOW_ACC));
+                }
+                e.setAttribute(MOUTH_DISTANCE, getLength(e) + maxMouthDist);
+            }
+        }
+    }
+
+
+    public MultiInputDialog initDialog(final PlugInContext context) {
+        final MultiInputDialog dialog = new MultiInputDialog(
+                context.getWorkbenchFrame(), STREAM_ORDER, true);
+        dialog.setSideBarImage(new 
ImageIcon(this.getClass().getResource("StrahlerNumber.png")));
+        
dialog.setSideBarDescription(I18NPlug.getI18N("StrahlerNumberPlugIn.description"));
+        dialog.addLayerComboBox(LAYER, context.getCandidateLayer(0), null, 
context.getLayerManager());
+        dialog.addCheckBox(OLD_ALGO, old_algo);
+        dialog.addCheckBox(SHREVE, shreve, SHREVE_TT);
+
+        // ---------- orders based on cumulative stream length flows ----------
+        dialog.addSeparator();
+        JCheckBox flowAccumulationCB = dialog.addCheckBox(METRICS, metrics);
+        JComboBox lengthAttributeCB = 
dialog.addAttributeComboBox(LENGTH_ATTRIBUTE, LAYER,
+                new AttributeTypeFilter(AttributeTypeFilter.GEOMETRY + 
AttributeTypeFilter.DOUBLE),
+                null);
+        lengthAttributeCB.setEnabled(metrics);
+        JCheckBox hortonCB = dialog.addCheckBox(HORTON, horton, HORTON_TT);
+        hortonCB.setEnabled(metrics);
+        JCheckBox hackCB = dialog.addCheckBox(HACK, hack, HACK_TT);
+        hackCB.setEnabled(metrics);
+        flowAccumulationCB.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent) {
+                lengthAttributeCB.setEnabled(flowAccumulationCB.isSelected());
+                hortonCB.setEnabled(flowAccumulationCB.isSelected());
+                hackCB.setEnabled(flowAccumulationCB.isSelected());
+            }
+        });
+        return dialog;
+    }
+
+
+
     ColorThemingStyle getColorThemingStyle() {
         BasicStyle dbs = new BasicStyle();   dbs.setLineColor(new 
Color(255,0,0));      dbs.setLineWidth(2);
         BasicStyle bs1  = new BasicStyle();  bs1.setLineColor(new 
Color(120,240,255));  bs1.setLineWidth(1);
@@ -304,7 +681,7 @@
         BasicStyle bs10 = new BasicStyle(); bs10.setLineColor(new Color(180,  
0,255)); bs10.setLineWidth(13);
         BasicStyle bs11 = new BasicStyle(); bs11.setLineColor(new Color(210,  
0,255)); bs11.setLineWidth(15);
         BasicStyle bs12 = new BasicStyle(); bs12.setLineColor(new Color(240,  
0,255)); bs12.setLineWidth(18);
-        ColorThemingStyle cts =  new ColorThemingStyle(STREAM_ORDER,
+        ColorThemingStyle cts =  new ColorThemingStyle(STRAHLER,
                 CollectionUtil.createMap(new Object[]{
                     1, bs1,
                     2, bs2,

Modified: 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph.properties
===================================================================
--- 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph.properties
        2020-10-02 14:29:59 UTC (rev 6565)
+++ 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph.properties
        2020-10-03 17:59:16 UTC (rev 6566)
@@ -117,8 +117,9 @@
 CycleFinderPlugIn.homogeneous-cycles = Homogeneous cycles
 CycleFinderPlugIn.heterogeneous-cycles = Heterogeneous cycles
 
-StrahlerNumberPlugIn.strahler-numbers = Strahler Numbers
-StrahlerNumberPlugIn.description = This plugin adds an attribute containing 
the Strahler Number.\
+StrahlerNumberPlugIn.stream-order = Stream order
+StrahlerNumberPlugIn.description = This plugin creates a new Layer containing 
the Strahler Stream Order \
+  and optionally, some other stream ordering of a hydrographic network.\
   The Strahler number qualifies each edge of a hierarchical network. The value 
is 1 for source edges, \
   and n+1 for an edge with at least two parents of value n.\nWarning : 
presence of cycles in the \
   graph break the algorithm which will set a null value to all edges flowing 
from a cycle edge.\n\
@@ -127,6 +128,12 @@
   braided networks (see documentation), and is way more efficient (both from a 
memory and from a speed \
   perspective).
 StrahlerNumberPlugIn.old-algorithm = Old algorithm (legacy)
+StrahlerNumberPlugIn.strahler-tt = Strahler's stream order
+StrahlerNumberPlugIn.shreve-tt = Shreve's stream magnitude
+StrahlerNumberPlugIn.metrics = Flow accumulation and max distance to the source
+StrahlerNumberPlugIn.length-attribute = Length attribute
+StrahlerNumberPlugIn.horton-tt = Horton's stream order
+StrahlerNumberPlugIn.hack-tt = Hack's stream order
 
 SkeletonPlugIn = Skeleton
 SkeletonPlugIn.skeletonize = Skeletonize

Modified: 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_cz.properties
===================================================================
--- 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_cz.properties
     2020-10-02 14:29:59 UTC (rev 6565)
+++ 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_cz.properties
     2020-10-03 17:59:16 UTC (rev 6566)
@@ -111,8 +111,9 @@
 CycleFinderPlugIn.homogeneous-cycles = Stejnorod\u00E9 kruhy
 CycleFinderPlugIn.heterogeneous-cycles = Nestejnorod\u00E9 kruhy
 
-StrahlerNumberPlugIn.strahler-numbers = Strahler Numbers
-StrahlerNumberPlugIn.description = This plugin adds an attribute containing 
the Strahler Number.\
+StrahlerNumberPlugIn.stream-order = Stream order
+StrahlerNumberPlugIn.description = This plugin creates a new Layer containing 
the Strahler Stream Order \
+  and optionally, some other stream ordering of a hydrographic network.\
   The Strahler number qualifies each edge of a hierarchical network. The value 
is 1 for source edges, \
   and n+1 for an edge with at least two parents of value n.\nWarning : 
presence of cycles in the \
   graph break the algorithm which will set a null value to all edges flowing 
from a cycle edge.\n\
@@ -121,6 +122,13 @@
   braided networks (see documentation), and is way more efficient (both from a 
memory and from a speed \
   perspective).
 StrahlerNumberPlugIn.old-algorithm = Old algorithm (legacy)
+StrahlerNumberPlugIn.old-algorithm = Old algorithm (legacy)
+StrahlerNumberPlugIn.strahler-tt = Strahler's stream order
+StrahlerNumberPlugIn.shreve-tt = Shreve's stream magnitude
+StrahlerNumberPlugIn.metrics = Flow accumulation and max distance to the source
+StrahlerNumberPlugIn.length-attribute = Length attribute
+StrahlerNumberPlugIn.horton-tt = Horton's stream order
+StrahlerNumberPlugIn.hack-tt = Hack's stream order
   
 SkeletonPlugIn = #T: Skeleton
 SkeletonPlugIn.skeletonize = #T: Skeletonize

Modified: 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_fi.properties
===================================================================
--- 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_fi.properties
     2020-10-02 14:29:59 UTC (rev 6565)
+++ 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_fi.properties
     2020-10-03 17:59:16 UTC (rev 6566)
@@ -105,7 +105,7 @@
 use-attribute=K\u00E4yt\u00E4 ominaisuustietoa
 use-attribute-tooltip=Luo erilliset graafit jokaiselle ominaisuustiedon arvolle
 
-StrahlerNumberPlugIn.strahler-numbers = Strahlerin numerot
+StrahlerNumberPlugIn.stream-order = Stream order
 StrahlerNumberPlugIn.description = T\u00E4m\u00E4 laajennus lis\u00E4\u00E4 
tasolle ominaisuuden johon tallennetaan Strahlerin numerot.\
   Strahlerin numero luokittelee hierarkisen verkon jokaisen s\u00E4rm\u00E4n. 
Arvo on 1 l\u00E4hdes\u00E4rmille, \
   ja n+1 jokaiselle s\u00E4rm\u00E4lle jolla on v\u00E4hint\u00E4\u00E4n 2 
emoa, jonka arvo on n.\n Varoitus : Jos tasossa on piirej\u00E4 niin \
@@ -115,6 +115,13 @@
   braided networks (see documentation), and is way more efficient (both from a 
memory and from a speed \
   perspective).
 StrahlerNumberPlugIn.old-algorithm = Old algorithm (legacy)
+StrahlerNumberPlugIn.old-algorithm = Old algorithm (legacy)
+StrahlerNumberPlugIn.strahler-tt = Strahler's stream order
+StrahlerNumberPlugIn.shreve-tt = Shreve's stream magnitude
+StrahlerNumberPlugIn.metrics = Flow accumulation and max distance to the source
+StrahlerNumberPlugIn.length-attribute = Length attribute
+StrahlerNumberPlugIn.horton-tt = Horton's stream order
+StrahlerNumberPlugIn.hack-tt = Hack's stream order
   
 SkeletonPlugIn=Luurankograafi
 SkeletonPlugIn.skeletonize = Luo luurankograafi

Modified: 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_fr.properties
===================================================================
--- 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_fr.properties
     2020-10-02 14:29:59 UTC (rev 6565)
+++ 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_fr.properties
     2020-10-03 17:59:16 UTC (rev 6566)
@@ -117,9 +117,10 @@
 CycleFinderPlugIn.homogeneous-cycles = Cycles homog\u00E8nes
 CycleFinderPlugIn.heterogeneous-cycles = Cycles h\u00E9t\u00E9rog\u00E8nes
 
-StrahlerNumberPlugIn.strahler-numbers = Nombres de Strahler
-StrahlerNumberPlugIn.description = Ce plugin ajoute un attribut contenant le 
nombre de Strahler.\
-  Le nombre de Strahler qualifie chaque arc d'un r\xE9seau hi\xE9rarchique. Un 
arc situ\xE9 \xE0 une source du r\xE9seau \
+StrahlerNumberPlugIn.stream-order = Ordre d'un cours d'eau
+StrahlerNumberPlugIn.description = Ce plugin cr\xE9e une nouvelle couche 
contenant l'ordre de Strahler \
+  de chaque tron\xE7on ainsi que d'autres ordres en option.\
+  L'ordre de Strahler qualifie chaque arc d'un r\xE9seau hi\xE9rarchique. Un 
arc situ\xE9 \xE0 une source du r\xE9seau \
   prend la valeur 1 tandis qu'un arc ayant au moins 2 ant\xE9c\xE9dents de 
valeur n prend la valeur n+1.\
   \nAttention : la pr\xE9sence de cycles casse l'algorithme qui affecte une 
valeur nulle \xE0 tous les arcs \
   descendant de l'un des arcs du cycle.\n\
@@ -127,6 +128,12 @@
   in braided and nonbraided networks". Il diff\xE8re de l'ancien par la 
fa\xE7on de g\xE9rer les r\xE9seaux anastamos\xE9s.\n\
   (cf. documentation), ainsi que par son efficacit\xE9 (tant en m\xE9moire 
qu'en vitesse d'ex\xE9cution).
 StrahlerNumberPlugIn.old-algorithm = Ancien algorithme (historique)
+StrahlerNumberPlugIn.strahler-tt = Ordre de Strahler
+StrahlerNumberPlugIn.shreve-tt = Magnitude de Shreve
+StrahlerNumberPlugIn.metrics = Flux cumul\xE9 et distance maximum \xE0 la 
source
+StrahlerNumberPlugIn.length-attribute = Attribut longueur
+StrahlerNumberPlugIn.horton-tt = Ordre de Horton
+StrahlerNumberPlugIn.hack-tt = Ordre de Hack
 
 SkeletonPlugIn = Squelettisation
 SkeletonPlugIn.skeletonize = Squelettiser

Modified: 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_it.properties
===================================================================
--- 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_it.properties
     2020-10-02 14:29:59 UTC (rev 6565)
+++ 
plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_it.properties
     2020-10-03 17:59:16 UTC (rev 6566)
@@ -101,8 +101,9 @@
 Layer=Livello
 Node=Nodo
 Nodes=Nodi
-StrahlerNumberPlugIn.strahler-numbers = Strahler Numbers
-StrahlerNumberPlugIn.description = This plugin adds an attribute containing 
the Strahler Number.\
+StrahlerNumberPlugIn.stream-order = Stream order
+StrahlerNumberPlugIn.description = This plugin creates a new Layer containing 
the Strahler Stream Order \
+  and optionally, some other stream ordering of a hydrographic network.\
   The Strahler number qualifies each edge of a hierarchical network. The value 
is 1 for source edges, \
   and n+1 for an edge with at least two parents of value n.\nWarning : 
presence of cycles in the \
   graph break the algorithm which will set a null value to all edges flowing 
from a cycle edge.\n\
@@ -111,6 +112,12 @@
   braided networks (see documentation), and is way more efficient (both from a 
memory and from a speed \
   perspective).
 StrahlerNumberPlugIn.old-algorithm = Old algorithm (legacy)
+StrahlerNumberPlugIn.strahler-tt = Strahler's stream order
+StrahlerNumberPlugIn.shreve-tt = Shreve's stream magnitude
+StrahlerNumberPlugIn.metrics = Flow accumulation and max distance to the source
+StrahlerNumberPlugIn.length-attribute = Length attribute
+StrahlerNumberPlugIn.horton-tt = Horton's stream order
+StrahlerNumberPlugIn.hack-tt = Hack's stream order (based on max length acc 
and total flow acc)
 
 use-attribute=Usa un attributo
 use-attribute-tooltip=Crea grafici distinti per didtinti valori di attributo



_______________________________________________
Jump-pilot-devel mailing list
Jump-pilot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel

Reply via email to