|   | 
| /* | 
| * Licensed to the Apache Software Foundation (ASF) under one | 
| * or more contributor license agreements.  See the NOTICE file | 
| * distributed with this work for additional information | 
| * regarding copyright ownership.  The ASF licenses this file | 
| * to you under the Apache License, Version 2.0 (the | 
| * "License"); you may not use this file except in compliance | 
| * with the License.  You may obtain a copy of the License at | 
| * | 
| *   http://www.apache.org/licenses/LICENSE-2.0 | 
| * | 
| * Unless required by applicable law or agreed to in writing, | 
| * software distributed under the License is distributed on an | 
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
| * KIND, either express or implied.  See the License for the | 
| * specific language governing permissions and limitations | 
| * under the License. | 
| */ | 
|   | 
|   | 
| /** | 
|  * AUTO-GENERATED FILE. DO NOT MODIFY. | 
|  */ | 
|   | 
| /* | 
| * Licensed to the Apache Software Foundation (ASF) under one | 
| * or more contributor license agreements.  See the NOTICE file | 
| * distributed with this work for additional information | 
| * regarding copyright ownership.  The ASF licenses this file | 
| * to you under the Apache License, Version 2.0 (the | 
| * "License"); you may not use this file except in compliance | 
| * with the License.  You may obtain a copy of the License at | 
| * | 
| *   http://www.apache.org/licenses/LICENSE-2.0 | 
| * | 
| * Unless required by applicable law or agreed to in writing, | 
| * software distributed under the License is distributed on an | 
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
| * KIND, either express or implied.  See the License for the | 
| * specific language governing permissions and limitations | 
| * under the License. | 
| */ | 
|   | 
| /* | 
| * A third-party license is embeded for some of the code in this file: | 
| * Some formulas were originally copied from "d3.js" with some | 
| * modifications made for this project. | 
| * (See more details in the comment of the method "step" below.) | 
| * The use of the source code of this file is also subject to the terms | 
| * and consitions of the license of "d3.js" (BSD-3Clause, see | 
| * </licenses/LICENSE-d3>). | 
| */ | 
| import * as vec2 from 'zrender/lib/core/vector.js'; | 
| var scaleAndAdd = vec2.scaleAndAdd; // function adjacentNode(n, e) { | 
| //     return e.n1 === n ? e.n2 : e.n1; | 
| // } | 
|   | 
| export function forceLayout(inNodes, inEdges, opts) { | 
|   var nodes = inNodes; | 
|   var edges = inEdges; | 
|   var rect = opts.rect; | 
|   var width = rect.width; | 
|   var height = rect.height; | 
|   var center = [rect.x + width / 2, rect.y + height / 2]; // let scale = opts.scale || 1; | 
|   | 
|   var gravity = opts.gravity == null ? 0.1 : opts.gravity; // for (let i = 0; i < edges.length; i++) { | 
|   //     let e = edges[i]; | 
|   //     let n1 = e.n1; | 
|   //     let n2 = e.n2; | 
|   //     n1.edges = n1.edges || []; | 
|   //     n2.edges = n2.edges || []; | 
|   //     n1.edges.push(e); | 
|   //     n2.edges.push(e); | 
|   // } | 
|   // Init position | 
|   | 
|   for (var i = 0; i < nodes.length; i++) { | 
|     var n = nodes[i]; | 
|   | 
|     if (!n.p) { | 
|       n.p = vec2.create(width * (Math.random() - 0.5) + center[0], height * (Math.random() - 0.5) + center[1]); | 
|     } | 
|   | 
|     n.pp = vec2.clone(n.p); | 
|     n.edges = null; | 
|   } // Formula in 'Graph Drawing by Force-directed Placement' | 
|   // let k = scale * Math.sqrt(width * height / nodes.length); | 
|   // let k2 = k * k; | 
|   | 
|   | 
|   var initialFriction = opts.friction == null ? 0.6 : opts.friction; | 
|   var friction = initialFriction; | 
|   var beforeStepCallback; | 
|   var afterStepCallback; | 
|   return { | 
|     warmUp: function () { | 
|       friction = initialFriction * 0.8; | 
|     }, | 
|     setFixed: function (idx) { | 
|       nodes[idx].fixed = true; | 
|     }, | 
|     setUnfixed: function (idx) { | 
|       nodes[idx].fixed = false; | 
|     }, | 
|   | 
|     /** | 
|      * Before step hook | 
|      */ | 
|     beforeStep: function (cb) { | 
|       beforeStepCallback = cb; | 
|     }, | 
|   | 
|     /** | 
|      * After step hook | 
|      */ | 
|     afterStep: function (cb) { | 
|       afterStepCallback = cb; | 
|     }, | 
|   | 
|     /** | 
|      * Some formulas were originally copied from "d3.js" | 
|      * https://github.com/d3/d3/blob/b516d77fb8566b576088e73410437494717ada26/src/layout/force.js | 
|      * with some modifications made for this project. | 
|      * See the license statement at the head of this file. | 
|      */ | 
|     step: function (cb) { | 
|       beforeStepCallback && beforeStepCallback(nodes, edges); | 
|       var v12 = []; | 
|       var nLen = nodes.length; | 
|   | 
|       for (var i = 0; i < edges.length; i++) { | 
|         var e = edges[i]; | 
|   | 
|         if (e.ignoreForceLayout) { | 
|           continue; | 
|         } | 
|   | 
|         var n1 = e.n1; | 
|         var n2 = e.n2; | 
|         vec2.sub(v12, n2.p, n1.p); | 
|         var d = vec2.len(v12) - e.d; | 
|         var w = n2.w / (n1.w + n2.w); | 
|   | 
|         if (isNaN(w)) { | 
|           w = 0; | 
|         } | 
|   | 
|         vec2.normalize(v12, v12); | 
|         !n1.fixed && scaleAndAdd(n1.p, n1.p, v12, w * d * friction); | 
|         !n2.fixed && scaleAndAdd(n2.p, n2.p, v12, -(1 - w) * d * friction); | 
|       } // Gravity | 
|   | 
|   | 
|       for (var i = 0; i < nLen; i++) { | 
|         var n = nodes[i]; | 
|   | 
|         if (!n.fixed) { | 
|           vec2.sub(v12, center, n.p); // let d = vec2.len(v12); | 
|           // vec2.scale(v12, v12, 1 / d); | 
|           // let gravityFactor = gravity; | 
|   | 
|           scaleAndAdd(n.p, n.p, v12, gravity * friction); | 
|         } | 
|       } // Repulsive | 
|       // PENDING | 
|   | 
|   | 
|       for (var i = 0; i < nLen; i++) { | 
|         var n1 = nodes[i]; | 
|   | 
|         for (var j = i + 1; j < nLen; j++) { | 
|           var n2 = nodes[j]; | 
|           vec2.sub(v12, n2.p, n1.p); | 
|           var d = vec2.len(v12); | 
|   | 
|           if (d === 0) { | 
|             // Random repulse | 
|             vec2.set(v12, Math.random() - 0.5, Math.random() - 0.5); | 
|             d = 1; | 
|           } | 
|   | 
|           var repFact = (n1.rep + n2.rep) / d / d; | 
|           !n1.fixed && scaleAndAdd(n1.pp, n1.pp, v12, repFact); | 
|           !n2.fixed && scaleAndAdd(n2.pp, n2.pp, v12, -repFact); | 
|         } | 
|       } | 
|   | 
|       var v = []; | 
|   | 
|       for (var i = 0; i < nLen; i++) { | 
|         var n = nodes[i]; | 
|   | 
|         if (!n.fixed) { | 
|           vec2.sub(v, n.p, n.pp); | 
|           scaleAndAdd(n.p, n.p, v, friction); | 
|           vec2.copy(n.pp, n.p); | 
|         } | 
|       } | 
|   | 
|       friction = friction * 0.992; | 
|       var finished = friction < 0.01; | 
|       afterStepCallback && afterStepCallback(nodes, edges, finished); | 
|       cb && cb(finished); | 
|     } | 
|   }; | 
| } |