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ë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
[email protected]
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel