small bug fixes and dynamic springs

delete_edge
Ugo Finnendahl 5 years ago
parent 249f322c37
commit ed5e9e11d9
  1. 41
      frontend/assets/js/canvas.js
  2. 4
      main.py

@ -35,7 +35,7 @@ const node_text_layout = {
fontSize: 22, fontSize: 22,
width: 2 * node_size - 1, width: 2 * node_size - 1,
height: 2 * node_size - 1, height: 2 * node_size - 1,
fontFamily: 'Roboto', fontFamily: 'Roboto, Arial, Verdana, sans-serif',
fill: 'black', fill: 'black',
verticalAlign: 'middle', verticalAlign: 'middle',
align: 'center' align: 'center'
@ -50,7 +50,7 @@ const edge_text_layout = {
fontSize: 22, fontSize: 22,
width: 2 * node_size, width: 2 * node_size,
height: 2 * node_size, height: 2 * node_size,
fontFamily: 'Roboto', fontFamily: 'Roboto, Arial, Verdana, sans-serif',
fill: 'black', fill: 'black',
verticalAlign: 'middle', verticalAlign: 'middle',
align: 'center' align: 'center'
@ -103,10 +103,10 @@ function initialization() {
for (var i = 0; i < 1000; i++) { for (var i = 0; i < 1000; i++) {
force_directed_graph(); force_directed_graph();
} }
edge_layer.show(); edge_layer.show();
node_layer.draw();
} }
initialization();
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -135,6 +135,7 @@ function draw_new_node(name, x, y) {
let group = new Konva.Group({ let group = new Konva.Group({
x: x, x: x,
y: y, y: y,
dragDistance: 5,
draggable: true, draggable: true,
dragBoundFunc: function(pos) { dragBoundFunc: function(pos) {
return { return {
@ -186,7 +187,7 @@ function draw_new_edge(edge) {
let line = new Konva.Line(edge_layout); let line = new Konva.Line(edge_layout);
let simpleText = new Konva.Text({ let simpleText = new Konva.Text({
...edge_text_layout, ...edge_text_layout,
text: weight text: ""+weight
}); });
graph_copy[edge["start"]].push(edge["end"]); graph_copy[edge["start"]].push(edge["end"]);
@ -237,7 +238,7 @@ function draw_selected_nodes() {
reset_node_style(); reset_node_style();
reset_edge_style(); reset_edge_style();
for (let id in selected) { for (let id in selected) {
selected[id].children[0].strokeWidth(node_layout.strokeWidth + 1); selected[id].children[0].strokeWidth(node_layout.strokeWidth+1);
selected[id].children[0].stroke("rgb(240, 141, 25)"); selected[id].children[0].stroke("rgb(240, 141, 25)");
} }
node_layer.draw(); node_layer.draw();
@ -298,8 +299,8 @@ function create_node() {
state = "create_node"; state = "create_node";
// let mousePos = stage.getPointerPosition(); // let mousePos = stage.getPointerPosition();
let pos = { let pos = {
x: width / 2, x: (Math.random()-0.5)*node_size*4+width / 2,
y: height / 2 y: (Math.random()-0.5)*node_size*4+height / 2
}; };
create_input(pos.x, pos.y).then(function(text) { create_input(pos.x, pos.y).then(function(text) {
post("nodes", { post("nodes", {
@ -387,7 +388,6 @@ function find_path(data) {
show_error("Select at least 2 nodes."); show_error("Select at least 2 nodes.");
return; return;
} }
console.log(url + "paths/" + data[0].attrs.id + "/" + data[1].attrs.id);
fetch(url + "paths/" + data[0].attrs.id + "/" + data[1].attrs.id).then(res => res.json()) fetch(url + "paths/" + data[0].attrs.id + "/" + data[1].attrs.id).then(res => res.json())
.then(function(res) { .then(function(res) {
if (res["error"]) { if (res["error"]) {
@ -434,6 +434,9 @@ function toggle_auto_layout() {
function normalize(vec) { function normalize(vec) {
let l = Math.sqrt(vec[0] ** 2 + vec[1] ** 2); let l = Math.sqrt(vec[0] ** 2 + vec[1] ** 2);
if (l == 0){
return [vec[0], vec[1]];
}
return [vec[0] / l, vec[1] / l]; return [vec[0] / l, vec[1] / l];
} }
@ -463,15 +466,20 @@ function force_directed_graph(spring_length = 300, step = 0.004) {
let x2 = konva_nodes[jdx].getX(); let x2 = konva_nodes[jdx].getX();
let y2 = konva_nodes[jdx].getY(); let y2 = konva_nodes[jdx].getY();
let dir = normalize([x2 - x1, y2 - y1]); let dir = normalize([x2 - x1, y2 - y1]);
let dist = ((x1 - x2) ** 2 + (y1 - y2) ** 2); let dist = Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2);
if (dist == 0){
continue;
}
if (in_edges(konva_nodes[idx], konva_nodes[jdx])) { if (in_edges(konva_nodes[idx], konva_nodes[jdx])) {
let f = (dist / spring_length); let f = (dist**2 / spring_length);
attr[0] += f * dir[0]; attr[0] += f * dir[0];
attr[1] += f * dir[1]; attr[1] += f * dir[1];
} }
let f = (spring_length ** 2 / Math.sqrt(dist)); if (dist < width*0.4){
rep[0] -= f * dir[0]; let f = (spring_length ** 2 / dist);
rep[1] -= f * dir[1]; rep[0] -= f * dir[0];
rep[1] -= f * dir[1];
}
} }
let new_x = x1 + step * (rep[0] + attr[0]); let new_x = x1 + step * (rep[0] + attr[0]);
let new_y = y1 + step * (rep[1] + attr[1]); let new_y = y1 + step * (rep[1] + attr[1]);
@ -493,11 +501,14 @@ function force_directed_graph(spring_length = 300, step = 0.004) {
var anim = new Konva.Animation(function(frame) { var anim = new Konva.Animation(function(frame) {
if (auto_layout && focus) { if (auto_layout && focus) {
const step = 0.00025 * frame.timeDiff; const step = 0.00025 * frame.timeDiff;
force_directed_graph(300, step) let spring_factor = Math.min((konva_edges.length+konva_nodes.length-3)/20, 1);
force_directed_graph(150+(1-spring_factor)*180, step);
} }
}, node_layer); }, node_layer);
anim.start(); anim.start();
initialization();
// bug: this avoids glitches // bug: this avoids glitches
window.onfocus = function() {focus = true;}; window.onfocus = function() {focus = true;};
window.onblur = function() {focus = false;}; window.onblur = function() {focus = false;};

@ -1,4 +1,4 @@
from flask import Flask, jsonify, request, render_template from flask import Flask, jsonify, request, render_template, escape
import numpy as np import numpy as np
app = Flask(__name__) app = Flask(__name__)
@ -84,7 +84,7 @@ def create_node():
if name == "": if name == "":
return error("Name cannot be empty."), 400 return error("Name cannot be empty."), 400
if name in graph: if name in graph:
return error(f'Node with name "{name}" already exist.'), 400 return error(f'Node with name "{escape(name)}" already exist.'), 400
graph[name] = {} graph[name] = {}
return jsonify(name), 201 return jsonify(name), 201

Loading…
Cancel
Save