Make other nodes follow when dragging a node in Cytoscape.js - javascript

I'm new to cytoscape.js, I just want to make other nodes follow when dragging one node.
Appreciate your help

Write a listener, and update the other node positions appropriately in your callback:
eles.on()
node.position()

Here is how I did it. Note you have to save off the original positions at the grab event, and then update during the drag event.
function add_drag_listeners()
{
var all = cy.elements("node");
for (j = 0; j < all.length; j++)
{
cynode = all[j];
cynode.on("grab",handle_grab);
cynode.on("drag",handle_drag);
}
}
var grab_x = 0;
var grab_y = 0;
var drag_subgraph = [];
function handle_grab(evt)
{
grab_x = this.position().x ;
grab_y = this.position().y ;
var succ = this.successors();
drag_subgraph = [];
var succstr = "";
for (i = 0; i < succ.length; i++)
{
if (succ[i].isNode())
{
var old_x = succ[i].position().x;
var old_y = succ[i].position().y;
succstr += " " + succ[i].data("id");
drag_subgraph.push({old_x:old_x, old_y:old_y, obj:succ[i]});
}
}
}
function handle_drag(evt)
{
var new_x = this.position().x;
var new_y = this.position().y;
var delta_x = new_x - grab_x;
var delta_y = new_y - grab_y;
for (i = 0; i < drag_subgraph.length; i++)
{
var obj = drag_subgraph[i].obj;
var old_x = drag_subgraph[i].old_x;
var old_y = drag_subgraph[i].old_y;
var new_x = old_x + delta_x;
var new_y = old_y + delta_y;
obj.position({x:new_x, y:new_y});
}
}

Related

How to use the result of an IF statement as a variable

I have a code as follows:
function DetailFacture2() {
var ss = SpreadsheetApp.getActive();
var DetailDEVIS = SpreadsheetApp.setActiveSheet(ss.getSheetByName('DetailDEVIS'));
var FACTUREDevis = SpreadsheetApp.setActiveSheet(ss.getSheetByName('FACTUREDevis'));
var DetailFactureDevis = SpreadsheetApp.setActiveSheet(ss.getSheetByName('DetailFactureDevis'));
var lastrowpaste = FACTUREDevis.getLastRow();
var numrow = FACTUREDevis.getRange(lastrowpaste,13).getValue()
var lastrowpaste2 = DetailFactureDevis.getLastRow() - numrow +2;
var data = DetailDEVIS.getDataRange().getValues();
var DetailD = FACTUREDevis.getRange(lastrowpaste,2).getValue();
for(var i = 0; i<data.length;i++){
if(data[i][1] == DetailD){ //[1] because column B
var firstrowcopy = i+1;
Logger.log(firstrowcopy)
return (firstrowcopy)
}
}
};
It does return the correct value, but how do you use "firstrowcopy" as a fixed var?
I would like to use as follows:
function DetailFacture2() {
var ss = SpreadsheetApp.getActive();
var DetailDEVIS = SpreadsheetApp.setActiveSheet(ss.getSheetByName('DetailDEVIS'));
var FACTUREDevis = SpreadsheetApp.setActiveSheet(ss.getSheetByName('FACTUREDevis'));
var DetailFactureDevis = SpreadsheetApp.setActiveSheet(ss.getSheetByName('DetailFactureDevis'));
var lastrowpaste = FACTUREDevis.getLastRow();
var numrow = FACTUREDevis.getRange(lastrowpaste,13).getValue()
var lastrowpaste2 = DetailFactureDevis.getLastRow() - numrow +2;
var data = DetailDEVIS.getDataRange().getValues();
var DetailD = FACTUREDevis.getRange(lastrowpaste,2).getValue();
for(var i = 0; i<data.length;i++){
if(data[i][1] == DetailD){ //[1] because column B
var firstrowcopy = i+1;
var source = DetailDEVIS.getRange(firstrowcopy,1,numrow-1);
var destination = DetailFactureDevis.getRange(lastrowpaste2,3);
source.copyTo(destination);
}
}
};
But, as one would expect, it cannot work as it loops...
Not sure if I understand your question too. The code doesn't look well. Here is just my guess. Try to change the last lines this way:
// ...
var firstrowcopy = 0;
for (var i = 0; i < data.length; i++){
if(data[i][1] == DetailD){ //[1] because column B
firstrowcopy = i+1;
break;
}
}
var source = DetailDEVIS.getRange(firstrowcopy,1,numrow-1);
var destination = DetailFactureDevis.getRange(lastrowpaste2,3);
source.copyTo(destination);
}

.remove is not function How to fix?

var dbRefObjectHis = firebase.database().ref('Box1').child('history');
dbRefObjectHis.on('value',gotData, errData);
function gotData(data) {
var ref = d3.selectAll('.His');
for (var i = 0; i < ref.length; i++){
ref[i].remove();
}
var history = data.val();
var keys = Object.keys(history);
for (i = 0; i < keys.length; i++) {
var k = keys[i];
var humidity = history[k].humidity;
var temperature = history[k].temperature;
$('.His').append('Humidity:' + humidity + 'Temperature:' + temperature );
}
This happens when the element you are trying to remove is not a removable Node.
try replacing
for (var i = 0; i < ref.length; i++){
ref[i].remove();
}
with
ref.forEach(function(e) {
e.remove();
});

How to generate random divs but not overlap

I want to generate random divs but not overlap with JavaScript.
Just like this:
random div example
But when the number of DIVS gets larger the browser will be blocked!
Then I use the Web Workers to generate the random divs,the browser will be blocked too.
here is my main js code:
self.onmessage = function(e){
var itemslength = e.data;
console.log(itemslength);
var position = [];
for(var i = 0 ; i < itemslength ; i++){
var length = position.length;
if(length == 0){
x = 900*Math.random();
y = 400*Math.random();
var relxy = [x,y];
position.push(relxy);
}else{
var flag = true;
x = 900*Math.random();
y = 400*Math.random();
do{
console.log('RUNNING!!');
x = x + 50;
y = y + 50;
var relxy = [x,y];
for(var j = 0 ; j < length ; j++){
var x1 = position[j][0];
var y1 = position[j][1];
var z = (x - x1)*(x - x1) + (y - y1)*(y - y1);
if(z > 10000){
flag = flag && true;
}else{
flag = flag && false;
}
}
}while(!flag);
position.push(relxy);
}
}
console.log('FINSHED!!');
postMessage(position);
};
<script>
var worker = new Worker('./js/bubbleworker.js');
var itemslengh = $('.items').length;
worker.postMessage(itemslengh);
worker.onmessage = function(data){
for(var i=0;i<data.data.length;i++){
var x = data.data[i][0];
var y = data.data[i][1];
$('.items:eq(' + i + ')').css({
'position':'absolute','left':x + 'px','top':y + 'px'
})
}
}
</script>
Am i right?
Someone who has a better idea? Thanks!

Detect coherent neighbors / neighborhood in 2d array

Im having an arbitrary 2d array and each field has an id and a teamid (here illustrated as colors 1).
I want for every neighborhood an array with the ids
in it.
A neighborhood consists of fields with neighbors with the same teamid horizontally and vertically (not diagonally)
e.g.:
This is what i have:
array[0][0] = {id:1,teamId:1}
array[1][0] = {id:2,teamId:1}
array[2][0] = {id:3,teamId:0}
array[3][0] = {id:4,teamId:2}
array[4][0] = {id:5,teamId:2}
array[5][0] = {id:6,teamId:0}
array[0][1] = {id:7,teamId:1}
array[1][1] = {id:8,teamId:1}
array[2][1] = {id:9,teamId:1}
array[3][1] = {id:10,teamId:2}
array[4][1] = {id:11,teamId:2}
array[5][1] = {id:12,teamId:0}
//and so on..
This is what i want:
neighborhood[1] = [1,2,7,8,9,13,14]
neighborhood[2] = [4,5,10,11]
neighborhood[3] = [16,22,23,24,29,30]
neighborhood[4] = [25,31,32,37,38]
neighborhood[5] = [35,41]
I am not searching for the images, but for the array
neighborhood
thanks in advance!
You can use the logic from dots and block games. A block belongs to a player if he has surrounded it with the walls. So, you need for each cell also 4 walls except for the outer cells. To test if a cell is closed you can use 4 class variables:
var Block = function() {
this.isclosed=0;
this.left=0;
this.top=0;
this.right=0;
this.bottom=0;
return this;
}
Block.prototype = {
isClosed : function () {
if (this.isclosed==true) {
return false;
} else if (this.left && this.top && this.right && this.bottom) {
this.isclosed=true;
return true;
} else {
return this.left && this.top && this.right && this.bottom;
}
}
}
You can try my implementations of dots and blocks game # https://dotsgame.codeplex.com/.
The method for solving this issue is refered as Connected Component Labelling
A similar question was asked once before from which i have my solution:
// matrix dimensions
var row_count = 20;
var col_count = 20;
var numOfTeams = 2;
// the input matrix
var m = [];
// the labels, 0 means unlabeled
var label = [];
var source = document.getElementById("source");
for (var i = 0; i < row_count; i++) {
var row = source.insertRow(0);
m[i] = [];
label[i] = [];
for (var j = 0; j < col_count; j++) {
//m[i][j] = Math.round(Math.random());
m[i][j] = getRandomInt(0, numOfTeams + 1);
label[i][j] = 0;
var cell1 = row.insertCell(0);
cell1.innerHTML = m[i][j];
}
}
// direction vectors
var dx = [1, 0, -1, 0];
var dy = [0, 1, 0, -1];
function dfs(x, y, current_label, team) {
if (x < 0 || x == row_count) return; // out of bounds
if (y < 0 || y == col_count) return; // out of bounds
if (label[x][y] || team != m[x][y]) return; // already labeled or not marked with 1 in m
// mark the current cell
label[x][y] = current_label;
// recursively mark the neighbors
for (var direction = 0; direction < 4; ++direction) {
dfs(x + dx[direction], y + dy[direction], current_label, team);
}
}
function find_components() {
var component = 0;
for (var i = 0; i < row_count; ++i) {
for (var j = 0; j < col_count; ++j) {
if (!label[i][j] && m[i][j]) dfs(i, j, ++component, m[i][j]);
}
}
}
find_components();
var result = document.getElementById("result");
for (var i in label) {
var string = ""
var row = result.insertRow(0);
for (var j in label[i]) {
string += label[i][j] + " "
var cell1 = row.insertCell(0);
cell1.innerHTML = label[i][j];
}
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
table tr td {
min-width: 14px
}
<div style="float:left">
<table id="source"></table>
</div>
<div style="float:right">
<table id="result"></table>
</div>

Neural network in Javascript not learning properly

I've tried to rewrite neural network found here to javascript. My javascript code looks like this.
function NeuralFactor(weight) {
var self = this;
this.weight = weight;
this.delta = 0;
}
function Sigmoid(value) {
return 1 / (1 + Math.exp(-value));
}
function Neuron(isInput) {
var self = this;
this.pulse = function() {
self.output = 0;
self.input.forEach(function(item) {
self.output += item.signal.output * item.factor.weight;
});
self.output += self.bias.weight;
self.output = Sigmoid(self.output);
};
this.bias = new NeuralFactor(isInput ? 0 : Math.random());
this.error = 0;
this.input = [];
this.output = 0;
this.findInput = function(signal) {
var input = self.input.filter(function(input) {
return signal == input.signal;
})[0];
return input;
};
}
function NeuralLayer() {
var self = this;
this.pulse = function() {
self.neurons.forEach(function(neuron) {
neuron.pulse();
});
};
this.neurons = [];
this.train = function(learningRate) {
self.neurons.forEach(function(neuron) {
neuron.bias.weight += neuron.bias.delta * learningRate;
neuron.bias.delta = 0;
neuron.input.forEach(function(input) {
input.factor.weight += input.factor.delta * learningRate;
input.factor.delta = 0;
})
})
}
}
function NeuralNet(inputCount, hiddenCount, outputCount) {
var self = this;
this.inputLayer = new NeuralLayer();
this.hiddenLayer = new NeuralLayer();
this.outputLayer = new NeuralLayer();
this.learningRate = 0.5;
for(var i = 0; i < inputCount; i++)
self.inputLayer.neurons.push(new Neuron(true));
for(var i = 0; i < hiddenCount; i++)
self.hiddenLayer.neurons.push(new Neuron());
for(var i = 0; i < outputCount; i++)
self.outputLayer.neurons.push(new Neuron());
for (var i = 0; i < hiddenCount; i++)
for (var j = 0; j < inputCount; j++)
self.hiddenLayer.neurons[i].input.push({
signal: self.inputLayer.neurons[j],
factor: new NeuralFactor(Math.random())
});
for (var i = 0; i < outputCount; i++)
for (var j = 0; j < hiddenCount; j++)
self.outputLayer.neurons[i].input.push({
signal: self.hiddenLayer.neurons[j],
factor: new NeuralFactor(Math.random())
});
this.pulse = function() {
self.hiddenLayer.pulse();
self.outputLayer.pulse();
};
this.backPropagation = function(desiredResults) {
for(var i = 0; i < self.outputLayer.neurons.length; i++) {
var outputNeuron = self.outputLayer.neurons[i];
var output = outputNeuron.output;
outputNeuron.error = (desiredResults[i] - output) * output * (1.0 - output);
}
for(var i = 0; i < self.hiddenLayer.neurons.length; i++) {
var hiddenNeuron = self.hiddenLayer.neurons[i];
var error = 0;
for(var j = 0; j < self.outputLayer.neurons.length; j++) {
var outputNeuron = self.outputLayer.neurons[j];
error += outputNeuron.error * outputNeuron.findInput(hiddenNeuron).factor.weight * hiddenNeuron.output * (1.0 - hiddenNeuron.output);
}
hiddenNeuron.error = error;
}
for(var j = 0; j < self.outputLayer.neurons.length; j++) {
var outputNeuron = self.outputLayer.neurons[j];
for(var i = 0; i < self.hiddenLayer.neurons.length; i++) {
var hiddenNeuron = self.hiddenLayer.neurons[i];
outputNeuron.findInput(hiddenNeuron).factor.delta += outputNeuron.error * hiddenNeuron.output;
}
outputNeuron.bias.delta += outputNeuron.error * outputNeuron.bias.weight;
}
for(var j = 0; j < self.hiddenLayer.neurons.length; j++) {
var hiddenNeuron = self.hiddenLayer.neurons[j];
for(var i = 0; i < self.inputLayer.neurons.length; i++) {
var inputNeuron = self.inputLayer.neurons[i];
hiddenNeuron.findInput(inputNeuron).factor.delta += hiddenNeuron.error * inputNeuron.output;
}
hiddenNeuron.bias.delta += hiddenNeuron.error * hiddenNeuron.bias.weight;
}
};
this.train = function(input, desiredResults) {
for(var i = 0; i < self.inputLayer.neurons.length; i++) {
var neuron = self.inputLayer.neurons[i];
neuron.output = input[i];
}
self.pulse();
self.backPropagation(desiredResults);
self.hiddenLayer.train(self.learningRate);
self.outputLayer.train(self.learningRate);
};
}
Now I'm trying to learn it how to resolve XOR problem. I'm teaching it like this:
var net = new NeuralNet(2,2,1);
var testInputs = [[0,0], [0,1], [1,0], [1,1]];
var testOutputs = [[1],[0],[0],[1]];
for (var i = 0; i < 1000; i++)
for(var j = 0; j < 4; j++)
net.train(testInputs[j], testOutputs[j]);
function UseNet(a, b) {
net.inputLayer.neurons[0].output = a;
net.inputLayer.neurons[1].output = b;
net.pulse();
return net.outputLayer.neurons[0].output;
}
The problem is that all results that I get is close to 0.5 and pretty random, no matter what arguments I use. For example:
UseNet(0,0) => 0.5107701166677714
UseNet(0,1) => 0.4801498747476413
UseNet(1,0) => 0.5142463167153447
UseNet(1,1) => 0.4881829364416052
What can be wrong with my code?
This network is big enough for the XOR problem and I can't see any obvious mistakes, so I suspect it's getting stuck in a local minimum.
Try going through the training set 10,000 times instead of 1000; this gives it a better chance of breaking out of any minima and converging. You can also increase convergence a lot by upping the number of hidden neurons, tweaking η (the learning rate) or adding momentum. To implement the latter, try using this as your training function:
this.train = function(learningRate) {
var momentum = 0 /* Some value, probably fairly small. */;
self.neurons.forEach(function(neuron) {
neuron.bias.weight += neuron.bias.delta * learningRate;
neuron.bias.delta = 0;
neuron.input.forEach(function(input) {
input.factor.weight += (input.factor.delta * learningRate) + (input.factor.weight * momentum);
input.factor.delta = 0;
})
})
}
I've had good results changing the learning rate to 1.5 (which is pretty high) and momentum to 0.000001 (which is pretty small).
(Incidentally, have you tried running the .NET implementation with a few different seeds? It can take quite a while to converge too!)
This system uses fuzzy logic. As it says in the article don't use integers instead use "close" real numbers as the article suggests -- try
UseNet(0.1,0.1) =>
UseNet(0.1,0.9) =>
UseNet(0.9,0.1) =>
UseNet(0.9,0.9) =>
For the results anything above 0.5 is a 1 and below is 0
Hmmmm
Try instead of:
var testInputs = [[0,0], [0,1], [1,0], [1,1]];
var testOutputs = [[1],[0],[0],[1]];
This:
var testInputs = [[0.05,0.05], [0.05,0.95], [0.95,0.05], [0.95,0.95]];
var testOutputs = [[1],[0],[0],[1]];
or
var testInputs = [[0,0], [0,1], [1,0], [1,1]];
var testOutputs = [[0.95],[0.05],[0.05],[0.95]];

Categories

Resources