corpus map : changed nodes display as 3 size squares, optimized code

This commit is contained in:
Bachir Soussi Chiadmi
2018-03-02 18:01:45 +01:00
parent 57fbb35060
commit 80afea9c7d
2 changed files with 200 additions and 138 deletions
@@ -20,7 +20,7 @@
(function($) { (function($) {
EdlpCorpus = function(){ EdlpCorpus = function(){
var _activated = false; var _activated = true;
var _$container = $('body'); var _$container = $('body');
var _$canvas = $('<canvas id="corpus-map">').appendTo(_$container); var _$canvas = $('<canvas id="corpus-map">').appendTo(_$container);
var _canvas = _$canvas[0]; var _canvas = _$canvas[0];
@@ -35,7 +35,7 @@
// var _stage = new createjs.Stage('corpus-map'); // var _stage = new createjs.Stage('corpus-map');
var _nodes = []; var _nodes = [];
// var _particules = []; // var _particules = [];
var _base_radius = 3; // nodes radius (real radius, not diametre) // var _base_radius = 3; // nodes radius (real radius, not diametre)
var _p_velocity_factor = 0.5; var _p_velocity_factor = 0.5;
var _m_pos = {x:0, y:0}; var _m_pos = {x:0, y:0};
var _node_hover_id = -1; var _node_hover_id = -1;
@@ -134,21 +134,40 @@
this.debug = d; this.debug = d;
this.mass = 8; this.mass = 8;
this.base_radius = _base_radius; // define radius regarding entries length
this.g = { switch(true){
l : 1, // drawing line width case this.entrees.length > 1 & this.entrees.length <= 3:
s : 1 // drawing space between squares this.r = 7.5;
}; break;
this.real_radius = this.base_radius + (this.g.l+this.g.s)*this.entrees.length; case this.entrees.length > 3:
this.wall_limits = { this.r = 10;
top: _canvas_props.margin_top +this.real_radius, break;
right: _canvas.width -_canvas_props.margin_right -this.real_radius, default:
bottom: _canvas.height -_canvas_props.margin_bottom -this.real_radius, this.r = 5;
left: _canvas_props.margin_left +this.real_radius break;
} }
// this.base_radius = _base_radius;
// this.g = {
// l : 1, // drawing line width
// s : 1 // drawing space between squares
// };
// this.real_radius = this.base_radius + (this.g.l+this.g.s)*this.entrees.length;
// prototype function not available on construct :(
// this.calcWallLimits();
this.wall_limits = {
top: _canvas_props.margin_top +this.r,
right: _canvas.width -_canvas_props.margin_right -this.r,
bottom: _canvas.height -_canvas_props.margin_bottom -this.r,
left: _canvas_props.margin_left +this.r
}
this.x = this.wall_limits.left + Math.random()*(this.wall_limits.right - this.wall_limits.left); this.x = this.wall_limits.left + Math.random()*(this.wall_limits.right - this.wall_limits.left);
this.y = this.wall_limits.top + Math.random()*(this.wall_limits.bottom - this.wall_limits.top); this.y = this.wall_limits.top + Math.random()*(this.wall_limits.bottom - this.wall_limits.top);
this.e_color = 'e_col_'+this.entrees[Math.floor(Math.random(this.entrees.length))];
this.hover = false; this.hover = false;
// physics // physics
@@ -163,14 +182,17 @@
// // console.log("Node : init()", this); // // console.log("Node : init()", this);
// // this.draw(); // // this.draw();
// }; // };
Node.prototype.calcWallLimits = function(){
this.wall_limits = {
top: _canvas_props.margin_top +this.r,
right: _canvas.width -_canvas_props.margin_right -this.r,
bottom: _canvas.height -_canvas_props.margin_bottom -this.r,
left: _canvas_props.margin_left +this.r
}
};
Node.prototype.onResizeCanvas = function(){ Node.prototype.onResizeCanvas = function(){
this.wall_limits = { this.calcWallLimits();
top: _canvas_props.margin_top +this.real_radius,
right: _canvas.width -_canvas_props.margin_right -this.real_radius,
bottom: _canvas.height -_canvas_props.margin_bottom -this.real_radius,
left: _canvas_props.margin_left +this.real_radius
}
// TODO: when canvas is smaller what about nodes hors champs, they are coming back alone but it's too long // TODO: when canvas is smaller what about nodes hors champs, they are coming back alone but it's too long
}; };
@@ -207,10 +229,10 @@
Node.prototype.checkMouse = function(){ Node.prototype.checkMouse = function(){
if( _m_pos.x > this.x - this.real_radius if( _m_pos.x > this.x - this.r
&& _m_pos.x < this.x + this.real_radius && _m_pos.x < this.x + this.r
&& _m_pos.y > this.y - this.real_radius && _m_pos.y > this.y - this.r
&& _m_pos.y < this.y + this.real_radius){ && _m_pos.y < this.y + this.r){
if(_node_hover_id == -1 || _node_hover_id == this.id){ if(_node_hover_id == -1 || _node_hover_id == this.id){
// console.log("Node hover", this.id); // console.log("Node hover", this.id);
this.hover = true; this.hover = true;
@@ -238,22 +260,39 @@
} }
Node.prototype.draw = function(){ Node.prototype.draw = function(){
// carre plein
// clouleur aléatoire ds les entrees
// 3 tailles :
// - 1 entree : petit carre 5px
// - 2-3 entrees : moyen 7.5px
// - >3 entrees : grand 10px
// actif entouré de rouge
// var d = this.r*2; // diametre
_ctx.beginPath(); _ctx.beginPath();
_ctx.lineWidth = this.g.l*2;//this.hover ? this.g.l*2 : this.g.l; _ctx.fillStyle = edlp_vars[this.e_color];
var r,d; _ctx.fillRect(this.x - this.r,this.y - this.r,this.r*2,this.r*2);
for (let i = 0; i < this.entrees.length; i++) {
// _ctx.fillStyle = i == 0 ? _entrees_colors[this.entrees[i]] : "#fff";
// _ctx.strokeStyle = _entrees_colors[this.entrees[i]];
_ctx.fillStyle = i == 0 ? edlp_vars['e_col_'+this.entrees[i]] : "#fff";
_ctx.strokeStyle = edlp_vars['e_col_'+this.entrees[i]];
r = this.base_radius + (this.g.l+this.g.s)*i; // radius
d = r*2; // diametre
if (i == 0) {
_ctx.fillRect(this.x - r,this.y - r,d,d);
}
_ctx.strokeRect(this.x - r,this.y - r,d,d);
}
_ctx.closePath(); _ctx.closePath();
// _ctx.beginPath();
// _ctx.lineWidth = this.g.l*2;//this.hover ? this.g.l*2 : this.g.l;
// var r,d;
// for (let i = 0; i < this.entrees.length; i++) {
// // _ctx.fillStyle = i == 0 ? _entrees_colors[this.entrees[i]] : "#fff";
// // _ctx.strokeStyle = _entrees_colors[this.entrees[i]];
// _ctx.fillStyle = i == 0 ? edlp_vars['e_col_'+this.entrees[i]] : "#fff";
// _ctx.strokeStyle = edlp_vars['e_col_'+this.entrees[i]];
// r = this.base_radius + (this.g.l+this.g.s)*i; // radius
// d = r*2; // diametre
// if (i == 0) {
// _ctx.fillRect(this.x - r,this.y - r,d,d);
// }
// _ctx.strokeRect(this.x - r,this.y - r,d,d);
// }
// _ctx.closePath();
// _ctx.beginPath(); // _ctx.beginPath();
// _ctx.fillStyle = this.hover ? "red" : this.debug ? "blue" : "black"; // _ctx.fillStyle = this.hover ? "red" : this.debug ? "blue" : "black";
// _ctx.fillRect(this.x, this.y, this.base_radius, this.base_radius); // _ctx.fillRect(this.x, this.y, this.base_radius, this.base_radius);
@@ -275,67 +314,59 @@
// TODO: we may convert a lot of computation into a web worker https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers // TODO: we may convert a lot of computation into a web worker https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
function checkParticulesCollisions(){ function checkParticulesCollisions(){
// pre create vars to save memory; // pre create vars to save memory;
var node_a, node_b, p_a, p_b, var d, full_rad,
d, full_rad,
newVelX1, newVelY1, newVelX2, newVelY2, newVelX1, newVelY1, newVelX2, newVelY2,
makeup, angle; makeup, angle;
// colisions between _particules // colisions between _particules
for (var n = 0, l = _nodes.length; n < l; n++) { for (var n = 0, l = _nodes.length; n < l; n++) {
node_a = _nodes[n]; // do not collide attracacted away nodes
p_a = node_a.p;
// console.log(`p_a`, p_a.attracted);
// var theta = 360 / (Math.PI * _base_radius);
// if(!p_a.attracted) continue; // if(!p_a.attracted) continue;
// console.log('test');
for (var q = 0; q < n; q++) { for (var q = 0; q < n; q++) {
if(q===n) continue; if(q===n) continue;
node_b = _nodes[q]; p_b = _nodes[q].p;
p_b = node_b.p;
// if(!p_b.attracted) continue; // if(!p_b.attracted) continue;
d = p_a.distanceTo(p_b); d = _nodes[n].p.distanceTo(_nodes[q].p);
full_rad = node_a.real_radius + node_b.real_radius; full_rad = _nodes[n].r + _nodes[q].r;
// if not colliding skip following // if not colliding skip following
if(d > full_rad) continue; if(d > full_rad) continue;
// apply new forces if colliding // apply new forces if colliding
newVelX1 = (p_a.velocity.x * (p_a.mass - p_b.mass) newVelX1 = (_nodes[n].p.velocity.x * (_nodes[n].p.mass - _nodes[q].p.mass)
+ (2 * p_b.mass * p_b.velocity.x)) / (p_a.mass + p_b.mass); + (2 * _nodes[q].p.mass * _nodes[q].p.velocity.x)) / (_nodes[n].p.mass + _nodes[q].p.mass);
newVelY1 = (p_a.velocity.y * (p_a.mass - p_b.mass) newVelY1 = (_nodes[n].p.velocity.y * (_nodes[n].p.mass - _nodes[q].p.mass)
+ (2 * p_b.mass * p_b.velocity.y)) / (p_a.mass + p_b.mass); + (2 * _nodes[q].p.mass * _nodes[q].p.velocity.y)) / (_nodes[n].p.mass + _nodes[q].p.mass);
newVelX2 = (p_b.velocity.x * (p_b.mass - p_a.mass) newVelX2 = (_nodes[q].p.velocity.x * (_nodes[q].p.mass - _nodes[n].p.mass)
+ (2 * p_a.mass * p_a.velocity.x)) / (p_a.mass + p_b.mass); + (2 * _nodes[n].p.mass * _nodes[n].p.velocity.x)) / (_nodes[n].p.mass + _nodes[q].p.mass);
newVelY2 = (p_b.velocity.y * (p_b.mass - p_a.mass) newVelY2 = (_nodes[q].p.velocity.y * (_nodes[q].p.mass - _nodes[n].p.mass)
+ (2 * p_a.mass * p_a.velocity.y)) / (p_a.mass + p_b.mass); + (2 * _nodes[n].p.mass * _nodes[n].p.velocity.y)) / (_nodes[n].p.mass + _nodes[q].p.mass);
p_a.velocity.x = newVelX1; _nodes[n].p.velocity.x = newVelX1;
p_a.velocity.y = newVelY1; _nodes[n].p.velocity.y = newVelY1;
p_b.velocity.x = newVelX2; _nodes[q].p.velocity.x = newVelX2;
p_b.velocity.y = newVelY2; _nodes[q].p.velocity.y = newVelY2;
p_a.velocity.multiplyScalar(0.75); _nodes[n].p.velocity.multiplyScalar(0.85);
p_b.velocity.multiplyScalar(0.75); _nodes[q].p.velocity.multiplyScalar(0.85);
// move particles if they overlap // move particles if they overlap
if (d < full_rad) { if (d < full_rad) {
makeup = full_rad/2 - d/2; makeup = full_rad/2 - d/2;
angle = Math.atan2(p_b.position.y - p_a.position.y, p_b.position.x - p_a.position.x); angle = Math.atan2(_nodes[q].p.position.y - _nodes[n].p.position.y, _nodes[q].p.position.x - _nodes[n].p.position.x);
p_b.position.x += makeup * Math.cos(angle); _nodes[q].p.position.x += makeup * Math.cos(angle);
p_b.position.y += makeup * Math.sin(angle); _nodes[q].p.position.y += makeup * Math.sin(angle);
angle += Math.PI; angle += Math.PI;
p_a.position.x += makeup * Math.cos(angle); _nodes[n].p.position.x += makeup * Math.cos(angle);
p_a.position.y += makeup * Math.sin(angle); _nodes[n].p.position.y += makeup * Math.sin(angle);
} }
_nodes[n].p = p_a;
_nodes[q].p = p_b;
} }
} }
}; };
@@ -20,7 +20,7 @@
(function($) { (function($) {
EdlpCorpus = function(){ EdlpCorpus = function(){
var _activated = false; var _activated = true;
var _$container = $('body'); var _$container = $('body');
var _$canvas = $('<canvas id="corpus-map">').appendTo(_$container); var _$canvas = $('<canvas id="corpus-map">').appendTo(_$container);
var _canvas = _$canvas[0]; var _canvas = _$canvas[0];
@@ -35,7 +35,7 @@
// var _stage = new createjs.Stage('corpus-map'); // var _stage = new createjs.Stage('corpus-map');
var _nodes = []; var _nodes = [];
// var _particules = []; // var _particules = [];
var _base_radius = 3; // nodes radius (real radius, not diametre) // var _base_radius = 3; // nodes radius (real radius, not diametre)
var _p_velocity_factor = 0.5; var _p_velocity_factor = 0.5;
var _m_pos = {x:0, y:0}; var _m_pos = {x:0, y:0};
var _node_hover_id = -1; var _node_hover_id = -1;
@@ -134,21 +134,40 @@
this.debug = d; this.debug = d;
this.mass = 8; this.mass = 8;
this.base_radius = _base_radius; // define radius regarding entries length
this.g = { switch(true){
l : 1, // drawing line width case this.entrees.length > 1 & this.entrees.length <= 3:
s : 1 // drawing space between squares this.r = 7.5;
}; break;
this.real_radius = this.base_radius + (this.g.l+this.g.s)*this.entrees.length; case this.entrees.length > 3:
this.wall_limits = { this.r = 10;
top: _canvas_props.margin_top +this.real_radius, break;
right: _canvas.width -_canvas_props.margin_right -this.real_radius, default:
bottom: _canvas.height -_canvas_props.margin_bottom -this.real_radius, this.r = 5;
left: _canvas_props.margin_left +this.real_radius break;
} }
// this.base_radius = _base_radius;
// this.g = {
// l : 1, // drawing line width
// s : 1 // drawing space between squares
// };
// this.real_radius = this.base_radius + (this.g.l+this.g.s)*this.entrees.length;
// prototype function not available on construct :(
// this.calcWallLimits();
this.wall_limits = {
top: _canvas_props.margin_top +this.r,
right: _canvas.width -_canvas_props.margin_right -this.r,
bottom: _canvas.height -_canvas_props.margin_bottom -this.r,
left: _canvas_props.margin_left +this.r
}
this.x = this.wall_limits.left + Math.random()*(this.wall_limits.right - this.wall_limits.left); this.x = this.wall_limits.left + Math.random()*(this.wall_limits.right - this.wall_limits.left);
this.y = this.wall_limits.top + Math.random()*(this.wall_limits.bottom - this.wall_limits.top); this.y = this.wall_limits.top + Math.random()*(this.wall_limits.bottom - this.wall_limits.top);
this.e_color = 'e_col_'+this.entrees[Math.floor(Math.random(this.entrees.length))];
this.hover = false; this.hover = false;
// physics // physics
@@ -163,14 +182,17 @@
// // console.log("Node : init()", this); // // console.log("Node : init()", this);
// // this.draw(); // // this.draw();
// }; // };
Node.prototype.calcWallLimits = function(){
this.wall_limits = {
top: _canvas_props.margin_top +this.r,
right: _canvas.width -_canvas_props.margin_right -this.r,
bottom: _canvas.height -_canvas_props.margin_bottom -this.r,
left: _canvas_props.margin_left +this.r
}
};
Node.prototype.onResizeCanvas = function(){ Node.prototype.onResizeCanvas = function(){
this.wall_limits = { this.calcWallLimits();
top: _canvas_props.margin_top +this.real_radius,
right: _canvas.width -_canvas_props.margin_right -this.real_radius,
bottom: _canvas.height -_canvas_props.margin_bottom -this.real_radius,
left: _canvas_props.margin_left +this.real_radius
}
// TODO: when canvas is smaller what about nodes hors champs, they are coming back alone but it's too long // TODO: when canvas is smaller what about nodes hors champs, they are coming back alone but it's too long
}; };
@@ -207,10 +229,10 @@
Node.prototype.checkMouse = function(){ Node.prototype.checkMouse = function(){
if( _m_pos.x > this.x - this.real_radius if( _m_pos.x > this.x - this.r
&& _m_pos.x < this.x + this.real_radius && _m_pos.x < this.x + this.r
&& _m_pos.y > this.y - this.real_radius && _m_pos.y > this.y - this.r
&& _m_pos.y < this.y + this.real_radius){ && _m_pos.y < this.y + this.r){
if(_node_hover_id == -1 || _node_hover_id == this.id){ if(_node_hover_id == -1 || _node_hover_id == this.id){
// console.log("Node hover", this.id); // console.log("Node hover", this.id);
this.hover = true; this.hover = true;
@@ -238,22 +260,39 @@
} }
Node.prototype.draw = function(){ Node.prototype.draw = function(){
// carre plein
// clouleur aléatoire ds les entrees
// 3 tailles :
// - 1 entree : petit carre 5px
// - 2-3 entrees : moyen 7.5px
// - >3 entrees : grand 10px
// actif entouré de rouge
// var d = this.r*2; // diametre
_ctx.beginPath(); _ctx.beginPath();
_ctx.lineWidth = this.g.l*2;//this.hover ? this.g.l*2 : this.g.l; _ctx.fillStyle = edlp_vars[this.e_color];
var r,d; _ctx.fillRect(this.x - this.r,this.y - this.r,this.r*2,this.r*2);
for (let i = 0; i < this.entrees.length; i++) {
// _ctx.fillStyle = i == 0 ? _entrees_colors[this.entrees[i]] : "#fff";
// _ctx.strokeStyle = _entrees_colors[this.entrees[i]];
_ctx.fillStyle = i == 0 ? edlp_vars['e_col_'+this.entrees[i]] : "#fff";
_ctx.strokeStyle = edlp_vars['e_col_'+this.entrees[i]];
r = this.base_radius + (this.g.l+this.g.s)*i; // radius
d = r*2; // diametre
if (i == 0) {
_ctx.fillRect(this.x - r,this.y - r,d,d);
}
_ctx.strokeRect(this.x - r,this.y - r,d,d);
}
_ctx.closePath(); _ctx.closePath();
// _ctx.beginPath();
// _ctx.lineWidth = this.g.l*2;//this.hover ? this.g.l*2 : this.g.l;
// var r,d;
// for (let i = 0; i < this.entrees.length; i++) {
// // _ctx.fillStyle = i == 0 ? _entrees_colors[this.entrees[i]] : "#fff";
// // _ctx.strokeStyle = _entrees_colors[this.entrees[i]];
// _ctx.fillStyle = i == 0 ? edlp_vars['e_col_'+this.entrees[i]] : "#fff";
// _ctx.strokeStyle = edlp_vars['e_col_'+this.entrees[i]];
// r = this.base_radius + (this.g.l+this.g.s)*i; // radius
// d = r*2; // diametre
// if (i == 0) {
// _ctx.fillRect(this.x - r,this.y - r,d,d);
// }
// _ctx.strokeRect(this.x - r,this.y - r,d,d);
// }
// _ctx.closePath();
// _ctx.beginPath(); // _ctx.beginPath();
// _ctx.fillStyle = this.hover ? "red" : this.debug ? "blue" : "black"; // _ctx.fillStyle = this.hover ? "red" : this.debug ? "blue" : "black";
// _ctx.fillRect(this.x, this.y, this.base_radius, this.base_radius); // _ctx.fillRect(this.x, this.y, this.base_radius, this.base_radius);
@@ -275,67 +314,59 @@
// TODO: we may convert a lot of computation into a web worker https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers // TODO: we may convert a lot of computation into a web worker https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
function checkParticulesCollisions(){ function checkParticulesCollisions(){
// pre create vars to save memory; // pre create vars to save memory;
var node_a, node_b, p_a, p_b, var d, full_rad,
d, full_rad,
newVelX1, newVelY1, newVelX2, newVelY2, newVelX1, newVelY1, newVelX2, newVelY2,
makeup, angle; makeup, angle;
// colisions between _particules // colisions between _particules
for (var n = 0, l = _nodes.length; n < l; n++) { for (var n = 0, l = _nodes.length; n < l; n++) {
node_a = _nodes[n]; // do not collide attracacted away nodes
p_a = node_a.p;
// console.log(`p_a`, p_a.attracted);
// var theta = 360 / (Math.PI * _base_radius);
// if(!p_a.attracted) continue; // if(!p_a.attracted) continue;
// console.log('test');
for (var q = 0; q < n; q++) { for (var q = 0; q < n; q++) {
if(q===n) continue; if(q===n) continue;
node_b = _nodes[q]; p_b = _nodes[q].p;
p_b = node_b.p;
// if(!p_b.attracted) continue; // if(!p_b.attracted) continue;
d = p_a.distanceTo(p_b); d = _nodes[n].p.distanceTo(_nodes[q].p);
full_rad = node_a.real_radius + node_b.real_radius; full_rad = _nodes[n].r + _nodes[q].r;
// if not colliding skip following // if not colliding skip following
if(d > full_rad) continue; if(d > full_rad) continue;
// apply new forces if colliding // apply new forces if colliding
newVelX1 = (p_a.velocity.x * (p_a.mass - p_b.mass) newVelX1 = (_nodes[n].p.velocity.x * (_nodes[n].p.mass - _nodes[q].p.mass)
+ (2 * p_b.mass * p_b.velocity.x)) / (p_a.mass + p_b.mass); + (2 * _nodes[q].p.mass * _nodes[q].p.velocity.x)) / (_nodes[n].p.mass + _nodes[q].p.mass);
newVelY1 = (p_a.velocity.y * (p_a.mass - p_b.mass) newVelY1 = (_nodes[n].p.velocity.y * (_nodes[n].p.mass - _nodes[q].p.mass)
+ (2 * p_b.mass * p_b.velocity.y)) / (p_a.mass + p_b.mass); + (2 * _nodes[q].p.mass * _nodes[q].p.velocity.y)) / (_nodes[n].p.mass + _nodes[q].p.mass);
newVelX2 = (p_b.velocity.x * (p_b.mass - p_a.mass) newVelX2 = (_nodes[q].p.velocity.x * (_nodes[q].p.mass - _nodes[n].p.mass)
+ (2 * p_a.mass * p_a.velocity.x)) / (p_a.mass + p_b.mass); + (2 * _nodes[n].p.mass * _nodes[n].p.velocity.x)) / (_nodes[n].p.mass + _nodes[q].p.mass);
newVelY2 = (p_b.velocity.y * (p_b.mass - p_a.mass) newVelY2 = (_nodes[q].p.velocity.y * (_nodes[q].p.mass - _nodes[n].p.mass)
+ (2 * p_a.mass * p_a.velocity.y)) / (p_a.mass + p_b.mass); + (2 * _nodes[n].p.mass * _nodes[n].p.velocity.y)) / (_nodes[n].p.mass + _nodes[q].p.mass);
p_a.velocity.x = newVelX1; _nodes[n].p.velocity.x = newVelX1;
p_a.velocity.y = newVelY1; _nodes[n].p.velocity.y = newVelY1;
p_b.velocity.x = newVelX2; _nodes[q].p.velocity.x = newVelX2;
p_b.velocity.y = newVelY2; _nodes[q].p.velocity.y = newVelY2;
p_a.velocity.multiplyScalar(0.75); _nodes[n].p.velocity.multiplyScalar(0.85);
p_b.velocity.multiplyScalar(0.75); _nodes[q].p.velocity.multiplyScalar(0.85);
// move particles if they overlap // move particles if they overlap
if (d < full_rad) { if (d < full_rad) {
makeup = full_rad/2 - d/2; makeup = full_rad/2 - d/2;
angle = Math.atan2(p_b.position.y - p_a.position.y, p_b.position.x - p_a.position.x); angle = Math.atan2(_nodes[q].p.position.y - _nodes[n].p.position.y, _nodes[q].p.position.x - _nodes[n].p.position.x);
p_b.position.x += makeup * Math.cos(angle); _nodes[q].p.position.x += makeup * Math.cos(angle);
p_b.position.y += makeup * Math.sin(angle); _nodes[q].p.position.y += makeup * Math.sin(angle);
angle += Math.PI; angle += Math.PI;
p_a.position.x += makeup * Math.cos(angle); _nodes[n].p.position.x += makeup * Math.cos(angle);
p_a.position.y += makeup * Math.sin(angle); _nodes[n].p.position.y += makeup * Math.sin(angle);
} }
_nodes[n].p = p_a;
_nodes[q].p = p_b;
} }
} }
}; };