2019独角兽企业重金招聘Python工程师标准>>>
JS
function init() {if (window.goSamples) goSamples(); // init for these samples -- you don't need to call thisvar $ = go.GraphObject.make; // for conciseness in defining templatesmyDiagram =$(go.Diagram, "myDiagramDiv", // must be the ID or reference to div{initialAutoScale: go.Diagram.UniformToFill,padding: 10,contentAlignment: go.Spot.Center,layout: $(go.ForceDirectedLayout, { defaultSpringLength: 10 }),maxSelectionCount: 2});// define the Node templatemyDiagram.nodeTemplate =$(go.Node, "Horizontal",{ locationSpot: go.Spot.Center, // Node.location is the center of the ShapelocationObjectName: "SHAPE",selectionAdorned: false,selectionChanged: nodeSelectionChanged },$(go.Panel, "Auto",$(go.Shape, "Ellipse",{ name: "SHAPE",fill: "lightgray", // default value, but also data-boundstroke: "transparent", // modified by highlightingstrokeWidth: 2,desiredSize: new go.Size(30, 30),portId: "" }, // so links will go to the shape, not the whole nodenew go.Binding("fill", "isSelected", function(s, obj) { return s ? "red" : obj.part.data.color; }).ofObject()),$(go.TextBlock,new go.Binding("text", "distance", function(d) { if (d === Infinity) return "INF"; else return d | 0; }))),$(go.TextBlock,new go.Binding("text")));// define the Link templatemyDiagram.linkTemplate =$(go.Link,{selectable: false, // links cannot be selected by the usercurve: go.Link.Bezier,layerName: "Background" // don't cross in front of any nodes},$(go.Shape, // this shape only shows when it isHighlighted{ isPanelMain: true, stroke: null, strokeWidth: 5 },new go.Binding("stroke", "isHighlighted", function(h) { return h ? "red" : null; }).ofObject()),$(go.Shape,// mark each Shape to get the link geometry with isPanelMain: true{ isPanelMain: true, stroke: "black", strokeWidth: 1 },new go.Binding("stroke", "color")),$(go.Shape, { toArrow: "Standard" }));// Override the clickSelectingTool's standardMouseSelect// If less than 2 nodes are selected, always add to the selectionmyDiagram.toolManager.clickSelectingTool.standardMouseSelect = function() {var diagram = this.diagram;if (diagram === null || !diagram.allowSelect) return;var e = diagram.lastInput;var count = diagram.selection.count;var curobj = diagram.findPartAt(e.documentPoint, false);if (curobj !== null) {if (count < 2) { // add the part to the selectionif (!curobj.isSelected) {var part = curobj;if (part !== null) part.isSelected = true;}} else {if (!curobj.isSelected) {var part = curobj;if (part !== null) diagram.select(part);}}} else if (e.left && !(e.control || e.meta) && !e.shift) {// left click on background with no modifier: clear selectiondiagram.clearSelection();}}generateGraph();// select two nodes that connect from the first one to the second onevar num = myDiagram.model.nodeDataArray.length;var node1 = null;var node2 = null;for (var i = 0; i < num; i++) {node1 = myDiagram.findNodeForKey(i);var distances = findDistances(node1);for (var j = 0; j < num; j++) {node2 = myDiagram.findNodeForKey(j);var dist = distances.getValue(node2);if (dist > 1 && dist < Infinity) {node1.isSelected = true;node2.isSelected = true;break;}}if (myDiagram.selection.count > 0) break;}}function generateGraph() {var names = ["Joshua", "Kathryn", "Robert", "Jason", "Scott", "Betsy", "John","Walter", "Gabriel", "Simon", "Emily", "Tina", "Elena", "Samuel","Jacob", "Michael", "Juliana", "Natalie", "Grace", "Ashley", "Dylan"];var nodeDataArray = [];for (var i = 0; i < names.length; i++) {nodeDataArray.push({ key: i, text: names[i], color: go.Brush.randomColor(128, 240) });}var linkDataArray = [];var num = nodeDataArray.length;for (var i = 0; i < num * 2; i++) {var a = Math.floor(Math.random() * num);var b = Math.floor(Math.random() * num / 4) + 1;linkDataArray.push({ from: a, to: (a + b) % num, color: go.Brush.randomColor(0, 127) });}myDiagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);}// There are three bits of functionality here:// 1: findDistances(Node) computes the distance of each Node from the given Node.// This function is used by showDistances to update the model data.// 2: findShortestPath(Node, Node) finds a shortest path from one Node to another.// This uses findDistances. This is used by highlightShortestPath.// 3: collectAllPaths(Node, Node) produces a collection of all paths from one Node to another.// This is used by listAllPaths. The result is remembered in a global variable// which is used by highlightSelectedPath. This does not depend on findDistances.// Returns a Map of Nodes with distance values from the given source Node.// Assumes all links are unidirectional.function findDistances(source) {var diagram = source.diagram;// keep track of distances from the source nodevar distances = new go.Map(go.Node, "number");// all nodes start with distance Infinityvar nit = diagram.nodes;while (nit.next()) {var n = nit.value;distances.add(n, Infinity);}// the source node starts with distance 0distances.add(source, 0);// keep track of nodes for which we have set a non-Infinity distance,// but which we have not yet finished examiningvar seen = new go.Set(go.Node);seen.add(source);// keep track of nodes we have finished examining;// this avoids unnecessary traversals and helps keep the SEEN collection smallvar finished = new go.Set(go.Node);while (seen.count > 0) {// look at the unfinished node with the shortest distance so farvar least = leastNode(seen, distances);var leastdist = distances.getValue(least);// by the end of this loop we will have finished examining this LEAST nodeseen.remove(least);finished.add(least);// look at all Links connected with this nodevar it = least.findLinksOutOf();while (it.next()) {var link = it.value;var neighbor = link.getOtherNode(least);// skip nodes that we have finishedif (finished.contains(neighbor)) continue;var neighbordist = distances.getValue(neighbor);// assume "distance" along a link is unitary, but could be any non-negative number.var dist = leastdist + 1; //Math.sqrt(least.location.distanceSquaredPoint(neighbor.location));if (dist < neighbordist) {// if haven't seen that node before, add it to the SEEN collectionif (neighbordist === Infinity) {seen.add(neighbor);}// record the new best distance so far to that nodedistances.add(neighbor, dist);}}}return distances;}// This helper function finds a Node in the given collection that has the smallest distance.function leastNode(coll, distances) {var bestdist = Infinity;var bestnode = null;var it = coll.iterator;while (it.next()) {var n = it.value;var dist = distances.getValue(n);if (dist < bestdist) {bestdist = dist;bestnode = n;}}return bestnode;}// Find a path that is shortest from the BEGIN node to the END node.// (There might be more than one, and there might be none.)function findShortestPath(begin, end) {// compute and remember the distance of each node from the BEGIN nodedistances = findDistances(begin);// now find a path from END to BEGIN, always choosing the adjacent Node with the lowest distancevar path = new go.List();path.add(end);while (end !== null) {var next = leastNode(end.findNodesInto(), distances);if (next !== null) {if (distances.getValue(next) < distances.getValue(end)) {path.add(next); // making progress towards the beginning} else {next = null; // nothing better found -- stop looking}}end = next;}// reverse the list to start at the node closest to BEGIN that is on the path to END// NOTE: if there's no path from BEGIN to END, the first node won't be BEGIN!path.reverse();return path;}// Recursively walk the graph starting from the BEGIN node;// when reaching the END node remember the list of nodes along the current path.// Finally return the collection of paths, which may be empty.// This assumes all links are unidirectional.function collectAllPaths(begin, end) {var stack = new go.List(go.Node);var coll = new go.List(go.List);function find(source, end) {source.findNodesOutOf().each(function(n) {if (n === source) return; // ignore reflexive linksif (n === end) { // successvar path = stack.copy();path.add(end); // finish the path at the end nodecoll.add(path); // remember the whole path} else if (!stack.contains(n)) { // inefficient way to check having visitedstack.add(n); // remember that we've been here for this path (but not forever)find(n, end);stack.removeAt(stack.count - 1);} // else might be a cycle});}stack.add(begin); // start the path at the begin nodefind(begin, end);return coll;}// Return a string representation of a path for humans to read.function pathToString(path) {var s = path.length + ": ";for (var i = 0; i < path.length; i++) {if (i > 0) s += " -- ";s += path.elt(i).data.text;}return s;}// When a node is selected show distances from the first selected node.// When a second node is selected, highlight the shortest path between two selected nodes.// If a node is deselected, clear all highlights.function nodeSelectionChanged(node) {var diagram = node.diagram;if (diagram === null) return;diagram.clearHighlighteds();if (node.isSelected) {// when there is a selection made, always clear out the list of all pathsvar sel = document.getElementById("myPaths");sel.innerHTML = "";// show the distance for each node from the selected nodevar begin = diagram.selection.first();showDistances(begin);if (diagram.selection.count === 2) {var end = node; // just became selected// highlight the shortest pathhighlightShortestPath(begin, end);// list all pathslistAllPaths(begin, end);}}}// Have each node show how far it is from the BEGIN node.function showDistances(begin) {// compute and remember the distance of each node from the BEGIN nodedistances = findDistances(begin);// show the distance on each nodevar it = distances.iterator;while (it.next()) {var n = it.key;var dist = it.value;myDiagram.model.setDataProperty(n.data, "distance", dist);}}// Highlight links along one of the shortest paths between the BEGIN and the END nodes.// Assume links are unidirectional.function highlightShortestPath(begin, end) {highlightPath(findShortestPath(begin, end));}// List all paths from BEGIN to ENDfunction listAllPaths(begin, end) {// compute and remember all paths from BEGIN to END: Lists of Nodespaths = collectAllPaths(begin, end);// update the Selection element with a bunch of Option elements, one per pathvar sel = document.getElementById("myPaths");sel.innerHTML = ""; // clear out any old Option elementspaths.each(function(p) {var opt = document.createElement("option");opt.text = pathToString(p);sel.add(opt, null);});sel.onchange = highlightSelectedPath;}// A collection of all of the paths between a pair of nodes, a List of Lists of Nodesvar paths = null;// This is only used for listing all paths for the selection onchange event.// When the selected item changes in the Selection element,// highlight the corresponding path of nodes.function highlightSelectedPath() {var sel = document.getElementById("myPaths");var idx = sel.selectedIndex;var opt = sel.options[idx];var val = opt.value;highlightPath(paths.elt(sel.selectedIndex));}// Highlight a particular path, a List of Nodes.function highlightPath(path) {myDiagram.clearHighlighteds();for (var i = 0; i < path.count - 1; i++) {var f = path.elt(i);var t = path.elt(i + 1);f.findLinksTo(t).each(function(l) { l.isHighlighted = true; });}}
HTML
<div id="sample"><div id="myDiagramDiv" style="border: solid 1px black; background: white; width: 100%; height: 700px"></div>Click on a node to show distances from that node to each other node.Click on a second node to show a shortest path from the first node to the second node.(Note that there might not be any path between the nodes.)<p>Clicking on a third node will de-select the first two.</p><p>Here is a list of all paths between the first and second selected nodes.Select a path to highlight it in the diagram.</p><select id="myPaths" style="min-width:100px" size="10"></select>
</div>
效果
点击两个节点,如0和5:
获取到的节点路径:
点击上面的记录,则可以在上图中显示路径走向。
原文地址:http://gojs.net/latest/samples/distances.html