Revision: 6529 http://sourceforge.net/p/jump-pilot/code/6529 Author: michaudm Date: 2020-09-24 07:01:53 +0000 (Thu, 24 Sep 2020) Log Message: ----------- Improve strahler stream order calculation by two orders of magnitude
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/CycleFinderPlugIn.java plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/GraphExtension.java plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/GraphNodesPlugIn.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 Modified: plug-ins/GraphToolboxPlugin/trunk/build.xml =================================================================== --- plug-ins/GraphToolboxPlugin/trunk/build.xml 2020-09-23 18:48:37 UTC (rev 6528) +++ plug-ins/GraphToolboxPlugin/trunk/build.xml 2020-09-24 07:01:53 UTC (rev 6529) @@ -17,7 +17,7 @@ <property name="dist" value="dist" /> <property name="javadoc" value="javadoc" /> - <property name="version" value="0.6.3" /> + <property name="version" value="0.7.0" /> <!-- =================================================================== --> <!-- Defines the classpath used for compilation and test. --> @@ -37,7 +37,7 @@ <!-- =================================================================== --> <target name="compile" id="compile" depends="clean"> <mkdir dir="${build}"/> - <javac destdir="${build}" debug="true" deprecation="false" nowarn="true" source="1.5" target="1.5"> + <javac destdir="${build}" debug="true" deprecation="false" nowarn="true" source="1.8" target="1.8"> <src path="${src}"/> <classpath refid="classpath"/> <include name="**/*.java"/> Modified: plug-ins/GraphToolboxPlugin/trunk/doc/GraphToolboxExtension4OJ.odt =================================================================== (Binary files differ) Modified: plug-ins/GraphToolboxPlugin/trunk/doc/GraphToolboxExtension4OJ_fr.odt =================================================================== (Binary files differ) Modified: plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/CycleFinderPlugIn.java =================================================================== --- plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/CycleFinderPlugIn.java 2020-09-23 18:48:37 UTC (rev 6528) +++ plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/CycleFinderPlugIn.java 2020-09-24 07:01:53 UTC (rev 6529) @@ -463,7 +463,7 @@ } if (use_attribute && heterogeneous_cycles_FC.size()>0) { context.addLayer(StandardCategoryNames.RESULT, - layer.getName()+"-CyclesHeterog\xE8nes", heterogeneous_cycles_FC); + layer.getName()+"-CyclesHeterogènes", heterogeneous_cycles_FC); } if (homogeneous_cycles_FC.size() == 0 && heterogeneous_cycles_FC.size() == 0) { context.getWorkbenchFrame().warnUser(NO_CYCLE_FOUND); 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-09-23 18:48:37 UTC (rev 6528) +++ plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/GraphExtension.java 2020-09-24 07:01:53 UTC (rev 6529) @@ -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.6.3 (2019-06-24) + * @version 0.7.0 (2020-09-18) */ +//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 //version 0.6.1 (2018-06-17) refactor to use AbstractPlugIn parameters in GraphNodesPlugIn @@ -63,7 +64,7 @@ } public String getVersion() { - return "0.6.3 (2019-06-24)"; + return "0.7.0 (2020-09-23)"; } public void configure(PlugInContext context) throws Exception { Modified: plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/GraphNodesPlugIn.java =================================================================== --- plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/GraphNodesPlugIn.java 2020-09-23 18:48:37 UTC (rev 6528) +++ plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/GraphNodesPlugIn.java 2020-09-24 07:01:53 UTC (rev 6529) @@ -48,6 +48,8 @@ import fr.michaelm.jump.feature.jgrapht.*; import org.jgrapht.DirectedGraph; +import org.jgrapht.WeightedGraph; +import org.jgrapht.graph.DirectedWeightedPseudograph; /** * Creates a graph from a linear layer with JGraphT and returns degree 1 nodes @@ -312,7 +314,7 @@ outdegree0 = getBooleanParam(P_OUT_DEGREE_0); for (Object k : map.keySet()) { monitor.report(GRAPH_COMPUTATION + " (" + k + ")"); - DirectedGraph graph = (DirectedGraph)GraphFactory.createDirectedPseudograph(map.get(k), dim3); + DirectedWeightedPseudograph graph = (DirectedWeightedPseudograph)GraphFactory.createDirectedPseudograph(map.get(k), dim3); for (Iterator<INode> it = graph.vertexSet().iterator() ; it.hasNext() ; ) { INode node = it.next(); 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-09-23 18:48:37 UTC (rev 6528) +++ plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/StrahlerNumberPlugIn.java 2020-09-24 07:01:53 UTC (rev 6529) @@ -1,36 +1,21 @@ package fr.michaelm.jump.plugin.graph; -import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jump.I18N; import com.vividsolutions.jump.feature.*; import com.vividsolutions.jump.task.TaskMonitor; import com.vividsolutions.jump.util.CollectionUtil; -import com.vividsolutions.jump.workbench.model.Category; import com.vividsolutions.jump.workbench.model.Layer; import com.vividsolutions.jump.workbench.model.StandardCategoryNames; -import com.vividsolutions.jump.workbench.model.UndoableCommand; import com.vividsolutions.jump.workbench.plugin.*; import com.vividsolutions.jump.workbench.ui.GUIUtil; -import com.vividsolutions.jump.workbench.ui.HTMLFrame; import com.vividsolutions.jump.workbench.ui.MenuNames; import com.vividsolutions.jump.workbench.ui.MultiInputDialog; import com.vividsolutions.jump.workbench.ui.renderer.style.*; -import com.vividsolutions.jump.workbench.ui.style.StylePanel; -import de.latlon.deejump.plugin.style.DeeChangeStylesPlugIn; import fr.michaelm.jump.feature.jgrapht.FeatureAsEdge; import fr.michaelm.jump.feature.jgrapht.GraphFactory; import fr.michaelm.jump.feature.jgrapht.INode; -import org.jgrapht.DirectedGraph; -import org.jgrapht.Graph; -import org.jgrapht.Graphs; -import org.jgrapht.UndirectedGraph; -import org.jgrapht.alg.ConnectivityInspector; -import org.jgrapht.event.EdgeTraversalEvent; -import org.jgrapht.graph.DefaultDirectedGraph; -import org.jgrapht.graph.DirectedWeightedMultigraph; import org.jgrapht.graph.DirectedWeightedPseudograph; -import org.jgrapht.graph.WeightedPseudograph; -import org.jgrapht.traverse.BreadthFirstIterator; import javax.swing.*; import java.awt.*; @@ -44,24 +29,28 @@ private static String LAYER; - private static String GRAPH; private static String STRAHLER_NUMBERS; private static String GRAPH_COMPUTATION; + private static String OLD_ALGO; private static final String STREAM_ORDER = "StreamOrder"; - //private static final String STRAHLER_NUMBER = "StrahlerNb"; + private static final String SEGMENT_ORIGIN = "SegmentOrig"; Layer layer; + boolean old_algo = false; public String getName() {return "Graph nodes PlugIn";} public void initialize(final PlugInContext context) throws Exception { - GRAPH = I18NPlug.getI18N("Graph"); + String GRAPH = I18NPlug.getI18N("Graph"); + + LAYER = I18N.get("ui.GenericNames.LAYER"); GRAPH_COMPUTATION = I18NPlug.getI18N("Graph-computation"); STRAHLER_NUMBERS = I18NPlug.getI18N("StrahlerNumberPlugIn.strahler-numbers"); + OLD_ALGO = I18NPlug.getI18N("StrahlerNumberPlugIn.old-algorithm"); - context.getFeatureInstaller().addMainMenuItem( + context.getFeatureInstaller().addMainMenuPlugin( this, new String[]{MenuNames.PLUGINS, GRAPH}, STRAHLER_NUMBERS + "...", false, null, new MultiEnableCheck() @@ -76,6 +65,7 @@ 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); GUIUtil.centreOnWindow(dialog); dialog.setPreferredSize(new Dimension(400,480)); @@ -82,6 +72,7 @@ dialog.setVisible(true); if (dialog.wasOKPressed()) { layer = dialog.getLayer(LAYER); + old_algo = dialog.getBoolean(OLD_ALGO); return true; } else return false; @@ -94,9 +85,9 @@ FeatureCollection sourceFC = layer.getFeatureCollectionWrapper(); // Creates the schema for the output dataset (nodes) - final FeatureSchema newSchema = (FeatureSchema)sourceFC.getFeatureSchema().clone(); + final FeatureSchema newSchema = sourceFC.getFeatureSchema().clone(); newSchema.addAttribute(STREAM_ORDER, AttributeType.INTEGER); - //newSchema.addAttribute(STRAHLER_NUMBER, AttributeType.INTEGER); + newSchema.addAttribute(SEGMENT_ORIGIN, AttributeType.OBJECT); FeatureCollection resultFC = new FeatureDataset(newSchema); for (Object o : sourceFC.getFeatures()) { Feature f = (Feature)o; @@ -111,11 +102,21 @@ .createDirectedPseudograph(resultFC.getFeatures(), false); //HTMLFrame htmlFrame = context.getOutputFrame(); //htmlFrame.createNewDocument(); - Map<Integer,Set<Integer>> ancestorMap = new HashMap<Integer,Set<Integer>>(); + int count = 0; + int total = resultFC.size(); for (FeatureAsEdge arc : graph.edgeSet()) { if (arc.getAttribute(STREAM_ORDER) != null) continue; - computeStreamOrder(graph, arc, ancestorMap); + if (old_algo) computeOldStreamOrder(graph, arc); + else computeNewStreamOrder(graph, arc); + monitor.report(count++, total, " features processed"); } + // Change -1 (cycles or cycle successors) to null + for (FeatureAsEdge arc : graph.edgeSet()) { + Object order = arc.getAttribute(STREAM_ORDER); + if (order != null && (Integer)order == -1) { + arc.setAttribute(STREAM_ORDER,null); + } + } context.getLayerManager().addLayer(StandardCategoryNames.RESULT, layer.getName()+"-strahler",resultFC); Layer resultLayer = context.getLayerManager().getLayer(layer.getName() + "-strahler"); @@ -125,49 +126,170 @@ resultLayer.addStyle(getColorThemingStyle()); } - private void computeStreamOrder(DirectedWeightedPseudograph<INode,FeatureAsEdge> graph, - FeatureAsEdge arc, Map<Integer,Set<Integer>> ancestorMap) { - Set<Integer> ancestors = ancestorMap.get(arc.getID()); - if (ancestors == null) { - ancestors = new HashSet<Integer>(); - ancestorMap.put(arc.getID(), ancestors); - } + + /** + * This version of Stream Order calculation is a re-implementation of the very first + * version proposed in OpenJUMP which used too much memory. While the first version + * was storing a list of all ancestors of each edge in a map, this one computes the + * list of ancestors again and again. It is slower than the former version but can + * terminate on a computer with less RAM. + * The algorithm differs from the following (computeStreamOrder3) in the case where + * an edge has two input streams a and b with the same StreamOrder : + * In the following algorithm, if a and b have at least one common ancestor, the + * stream order of the downstream edge will not be incremented. + * In computeStreamOrder3, the downstream edge will not be incremented only if a and + * b have the same segment head (see comments in computeStreamOrder3 method). + * @param graph + * @param arc + */ + private void computeOldStreamOrder(DirectedWeightedPseudograph<INode,FeatureAsEdge> graph, + FeatureAsEdge arc) { + int maxOrder = 0; int occ = 0; + FeatureAsEdge maxUpstream = null; for (FeatureAsEdge upstream : graph.incomingEdgesOf(graph.getEdgeSource(arc))) { Object att = upstream.getAttribute(STREAM_ORDER); + // Process current stream only if all upstreams are already processed if (att == null) return; int upstreamOrder = (Integer)att; + // Case 1 : upstream order > all previous ones + // (when the loop is finished : upstreamOrder > all others) if (upstreamOrder > maxOrder) { maxOrder = upstreamOrder; - occ = 1; - ancestors.addAll(ancestorMap.get(upstream.getID())); - ancestors.add(upstream.getID()); + occ = 1; // there is only 1 upstream > all others + maxUpstream = upstream; } + // Case 2 : upstream order = max order of previous ones (ex aequo) else if (upstreamOrder == maxOrder) { - int card = ancestors.size(); - Set<Integer> newSet = ancestorMap.get(upstream.getID()); - ancestors.addAll(newSet); - if (ancestors.size() == card + newSet.size()) { - occ++; + if (!hasCommonAncestors(graph, upstream, maxUpstream)) { + occ++; // there are several upstreams = maxOrder } } + // If upstream order is < max, it does not contribute to downstream + // order calculation else; } - if (maxOrder == 0) arc.setAttribute(STREAM_ORDER, 1); + // Head water of a stream (edge without predecessor) has order 1 + if (maxOrder == 0) { + arc.setAttribute(STREAM_ORDER, 1); + } 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); } + // Try to compute stream order recursively on all downstream edges Set<FeatureAsEdge> downStreams = graph.outgoingEdgesOf(graph.getEdgeTarget(arc)); for (FeatureAsEdge downStream : downStreams) { // In case of anastomosis, compute the downstream edge only once if (downStream.getAttribute(STREAM_ORDER) == null) { - computeStreamOrder(graph, downStream, ancestorMap); + computeOldStreamOrder(graph, downStream); } } } + private Set<Integer> getAncestors(DirectedWeightedPseudograph<INode,FeatureAsEdge> graph, + FeatureAsEdge arc, Set<Integer> ancestors) { + for (FeatureAsEdge e : graph.incomingEdgesOf(graph.getEdgeSource(arc))) { + if (ancestors.contains(e.getID())) continue; + ancestors.add(e.getID()); + getAncestors(graph, e, ancestors); + } + return ancestors; + } + + private boolean hasCommonAncestors(DirectedWeightedPseudograph<INode,FeatureAsEdge> graph, + FeatureAsEdge arc1, FeatureAsEdge arc2) { + Set<Integer> ancestors1 = getAncestors(graph, arc1, new HashSet<>()); + Set<Integer> ancestors2 = getAncestors(graph, arc2, new HashSet<>()); + int card1 = ancestors1.size(); + int card2 = ancestors2.size(); + ancestors1.addAll(ancestors2); + return ancestors1.size() < card1 + card2; + } + + // Implements algorithm described in + // 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, + FeatureAsEdge arc) { + + Object streamOrder = arc.getAttribute(STREAM_ORDER); + // 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; + // Flag current edge to be able to identify cycles while exploring ancestors + // recursively + arc.setAttribute(STREAM_ORDER, -1); + + // Stream order of the current edge has not yet been computed. + // Compute predecessors stream order first (recursion) + Set<FeatureAsEdge> upStreams = graph.incomingEdgesOf(graph.getEdgeSource(arc)); + boolean cycle = false; + for (FeatureAsEdge upStream : upStreams) { + // Visit/compute ancestors recursively + computeNewStreamOrder(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); + assert upStreamOrder != null; // stream order is initialized to -1 in pre-order + if ((Integer)upStreamOrder == -1) { + cycle = true; + } + } + + // If one of the upstream is part of a cycle, current edge cannot be computed + if (cycle) { + return; + } + // We are now in the normal situation of an edge which has all its ancestors + // computed and which does not belong to a cycle nor have a cycle as ancestor + int maxOrder = 0; + INode maxOrderOrigin = null; + int occ = 0; + for (FeatureAsEdge upstream : graph.incomingEdgesOf(graph.getEdgeSource(arc))) { + Object att1 = upstream.getAttribute(STREAM_ORDER); + assert att1 != null; + + int upstreamOrder = (Integer)att1; + INode segmentOrigin = (INode)upstream.getAttribute(SEGMENT_ORIGIN); + // Case 1 : upstream order > all previous ones + if (upstreamOrder > maxOrder) { + maxOrderOrigin = segmentOrigin; + maxOrder = upstreamOrder; + occ = 1; + } + // Case 2 : upstream order = max order of previous ones (ex aequo) + else if (upstreamOrder == maxOrder) { + if (!segmentOrigin.equals(maxOrderOrigin)) { + occ++; + } + } + } + // Set the stream order and segment origin of the current edge + if (maxOrder == 0) { + arc.setAttribute(STREAM_ORDER, 1); + arc.setAttribute(SEGMENT_ORIGIN, graph.getEdgeSource(arc)); + } + else if (occ > 1) { + arc.setAttribute(STREAM_ORDER, maxOrder+1); + arc.setAttribute(SEGMENT_ORIGIN, graph.getEdgeSource(arc)); + } + else { + arc.setAttribute(STREAM_ORDER, maxOrder); + arc.setAttribute(SEGMENT_ORIGIN, maxOrderOrigin); + } + + } + + + 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); 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-09-23 18:48:37 UTC (rev 6528) +++ plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph.properties 2020-09-24 07:01:53 UTC (rev 6529) @@ -121,7 +121,12 @@ StrahlerNumberPlugIn.description = This plugin adds an attribute containing the Strahler Number.\ 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. + graph break the algorithm which will set a null value to all edges flowing from a cycle edge.\n\ + The new algorithm implements "A fast recursive GIS algorithm for computing Strahler stream order \ + in braided and nonbraided networks". It differs slightly from the old algorithm in the way to manage \ + braided networks (see documentation), and is way more efficient (both from a memory and from a speed \ + perspective). +StrahlerNumberPlugIn.old-algorithm = Old algorithm (legacy) 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-09-23 18:48:37 UTC (rev 6528) +++ plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_cz.properties 2020-09-24 07:01:53 UTC (rev 6529) @@ -115,7 +115,12 @@ StrahlerNumberPlugIn.description = This plugin adds an attribute containing the Strahler Number.\ 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. + graph break the algorithm which will set a null value to all edges flowing from a cycle edge.\n\ + The new algorithm implements "A fast recursive GIS algorithm for computing Strahler stream order \ + in braided and nonbraided networks". It differs slightly from the old algorithm in the way to manage \ + braided networks (see documentation), and is way more efficient (both from a memory and from a speed \ + perspective). +StrahlerNumberPlugIn.old-algorithm = Old algorithm (legacy) 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-09-23 18:48:37 UTC (rev 6528) +++ plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_fi.properties 2020-09-24 07:01:53 UTC (rev 6529) @@ -109,9 +109,14 @@ 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 \ - ne rikkovat algoritmin, joka siin\u00E4 tapauksessa asettaa tyhj\u00E4n arvon kaikille s\u00E4rmille jotka erkanevat piirin s\u00E4rmist\u00E4. + ne rikkovat algoritmin, joka siin\u00E4 tapauksessa asettaa tyhj\u00E4n arvon kaikille s\u00E4rmille jotka erkanevat piirin s\u00E4rmist\u00E4.\n\ + The new algorithm implements "A fast recursive GIS algorithm for computing Strahler stream order \ + in braided and nonbraided networks". It differs slightly from the old algorithm in the way to manage \ + braided networks (see documentation), and is way more efficient (both from a memory and from a speed \ + perspective). +StrahlerNumberPlugIn.old-algorithm = Old algorithm (legacy) - SkeletonPlugIn=Luurankograafi +SkeletonPlugIn=Luurankograafi SkeletonPlugIn.skeletonize = Luo luurankograafi SkeletonPlugIn.source-layer = L\u00E4ht\u00F6taso SkeletonPlugIn.auto-width-parameter = Automaattinen leveyden laskenta 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-09-23 18:48:37 UTC (rev 6528) +++ plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_fr.properties 2020-09-24 07:01:53 UTC (rev 6529) @@ -122,7 +122,11 @@ Le nombre 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. + descendant de l'un des arcs du cycle.\n\ + Le nouvel algorihme impl\xE9mente "A fast recursive GIS algorithm for computing Strahler stream order \ + 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) 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-09-23 18:48:37 UTC (rev 6528) +++ plug-ins/GraphToolboxPlugin/trunk/src/fr/michaelm/jump/plugin/graph/graph_it.properties 2020-09-24 07:01:53 UTC (rev 6529) @@ -105,7 +105,13 @@ StrahlerNumberPlugIn.description = This plugin adds an attribute containing the Strahler Number.\ 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. + graph break the algorithm which will set a null value to all edges flowing from a cycle edge.\n\ + The new algorithm implements "A fast recursive GIS algorithm for computing Strahler stream order \ + in braided and nonbraided networks". It differs slightly from the old algorithm in the way to manage \ + braided networks (see documentation), and is way more efficient (both from a memory and from a speed \ + perspective). +StrahlerNumberPlugIn.old-algorithm = Old algorithm (legacy) + 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