Thanks Michael. Interesting new featured -- Inviato da myMail per Android sabato, 03 ottobre 2020, 07:59PM +02:00 da jump-pilot-svn--- via Jump-pilot-devel jump-pilot-devel@lists.sourceforge.net :
>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 @@ > > > >- >+ > > > > >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 @@ > * >* CycleFinderPlugIn : computes a graph from a linear network and find base >cycles > * > * @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 graph, >+ private void computeLegacyStrahlerOrder(DirectedWeightedPseudograph 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 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 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 getAncestors(DirectedWeightedPseudograph graph, > FeatureAsEdge arc, Set 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 graph, >+ private void computeNewStrahlerOrder(DirectedWeightedPseudograph 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 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 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 >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 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 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 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 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 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 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
_______________________________________________ Jump-pilot-devel mailing list Jump-pilot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel