layout-base
Advanced tools
Comparing version 1.0.0 to 1.0.1
@@ -32,2 +32,3 @@ 'use strict'; | ||
layoutBase.LayoutConstants = require('./src/LayoutConstants'); | ||
layoutBase.NeedlemanWunsch = require('./src/util/alignment/NeedlemanWunsch'); | ||
@@ -34,0 +35,0 @@ module.exports = layoutBase; |
{ | ||
"name": "layout-base", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "Basic layout model and some utilities for Cytoscape.js layout extensions", | ||
@@ -5,0 +5,0 @@ "main": "layout-base.js", |
@@ -1,2 +0,3 @@ | ||
# layout-base | ||
layout-base | ||
================================================================================ | ||
@@ -3,0 +4,0 @@ ## Description |
@@ -110,2 +110,10 @@ var LGraphObject = require('./LGraphObject'); | ||
/** | ||
* This method returns half the diagonal length of this node. | ||
*/ | ||
LNode.prototype.getHalfTheDiagonal = function () { | ||
return Math.sqrt(this.rect.height * this.rect.height + | ||
this.rect.width * this.rect.width) / 2; | ||
}; | ||
LNode.prototype.setRect = function (upperLeft, dimension) | ||
@@ -112,0 +120,0 @@ { |
@@ -0,4 +1,21 @@ | ||
/** | ||
* This class maintains a list of static geometry related utility methods. | ||
* | ||
* | ||
* Copyright: i-Vis Research Group, Bilkent University, 2007 - present | ||
*/ | ||
const Point = require('./Point'); | ||
function IGeometry() { | ||
} | ||
/** | ||
* This method calculates *half* the amount in x and y directions of the two | ||
* input rectangles needed to separate them keeping their respective | ||
* positioning, and returns the result in the input array. An input | ||
* separation buffer added to the amount in both directions. We assume that | ||
* the two rectangles do intersect. | ||
*/ | ||
IGeometry.calcSeparationAmount = function (rectA, rectB, overlapAmount, separationBuffer) | ||
@@ -9,36 +26,88 @@ { | ||
} | ||
var directions = new Array(2); | ||
IGeometry.decideDirectionsForOverlappingNodes(rectA, rectB, directions); | ||
let directions = new Array(2); | ||
this.decideDirectionsForOverlappingNodes(rectA, rectB, directions); | ||
overlapAmount[0] = Math.min(rectA.getRight(), rectB.getRight()) - | ||
Math.max(rectA.x, rectB.x); | ||
Math.max(rectA.x, rectB.x); | ||
overlapAmount[1] = Math.min(rectA.getBottom(), rectB.getBottom()) - | ||
Math.max(rectA.y, rectB.y); | ||
Math.max(rectA.y, rectB.y); | ||
// update the overlapping amounts for the following cases: | ||
if ((rectA.getX() <= rectB.getX()) && (rectA.getRight() >= rectB.getRight())) | ||
{ | ||
/* Case x.1: | ||
* | ||
* rectA | ||
* | | | ||
* | _________ | | ||
* | | | | | ||
* |________|_______|______| | ||
* | | | ||
* | | | ||
* rectB | ||
*/ | ||
overlapAmount[0] += Math.min((rectB.getX() - rectA.getX()), | ||
(rectA.getRight() - rectB.getRight())); | ||
(rectA.getRight() - rectB.getRight())); | ||
} | ||
else if ((rectB.getX() <= rectA.getX()) && (rectB.getRight() >= rectA.getRight())) | ||
{ | ||
/* Case x.2: | ||
* | ||
* rectB | ||
* | | | ||
* | _________ | | ||
* | | | | | ||
* |________|_______|______| | ||
* | | | ||
* | | | ||
* rectA | ||
*/ | ||
overlapAmount[0] += Math.min((rectA.getX() - rectB.getX()), | ||
(rectB.getRight() - rectA.getRight())); | ||
(rectB.getRight() - rectA.getRight())); | ||
} | ||
if ((rectA.getY() <= rectB.getY()) && (rectA.getBottom() >= rectB.getBottom())) | ||
{ | ||
/* Case y.1: | ||
* ________ rectA | ||
* | | ||
* | | ||
* ______|____ rectB | ||
* | | | ||
* | | | ||
* ______|____| | ||
* | | ||
* | | ||
* |________ | ||
* | ||
*/ | ||
overlapAmount[1] += Math.min((rectB.getY() - rectA.getY()), | ||
(rectA.getBottom() - rectB.getBottom())); | ||
(rectA.getBottom() - rectB.getBottom())); | ||
} | ||
else if ((rectB.getY() <= rectA.getY()) && (rectB.getBottom() >= rectA.getBottom())) | ||
{ | ||
/* Case y.2: | ||
* ________ rectB | ||
* | | ||
* | | ||
* ______|____ rectA | ||
* | | | ||
* | | | ||
* ______|____| | ||
* | | ||
* | | ||
* |________ | ||
* | ||
*/ | ||
overlapAmount[1] += Math.min((rectA.getY() - rectB.getY()), | ||
(rectB.getBottom() - rectA.getBottom())); | ||
(rectB.getBottom() - rectA.getBottom())); | ||
} | ||
// find slope of the line passes two centers | ||
var slope = Math.abs((rectB.getCenterY() - rectA.getCenterY()) / | ||
(rectB.getCenterX() - rectA.getCenterX())); | ||
let slope = Math.abs((rectB.getCenterY() - rectA.getCenterY()) / | ||
(rectB.getCenterX() - rectA.getCenterX())); | ||
// if centers are overlapped | ||
if ((rectB.getCenterY() == rectA.getCenterY()) && | ||
(rectB.getCenterX() == rectA.getCenterX())) | ||
if ((rectB.getCenterY() === rectA.getCenterY()) && | ||
(rectB.getCenterX() === rectA.getCenterX())) | ||
{ | ||
@@ -49,4 +118,4 @@ // assume the slope is 1 (45 degree) | ||
var moveByY = slope * overlapAmount[0]; | ||
var moveByX = overlapAmount[1] / slope; | ||
let moveByY = slope * overlapAmount[0]; | ||
let moveByX = overlapAmount[1] / slope; | ||
if (overlapAmount[0] < moveByX) | ||
@@ -64,4 +133,12 @@ { | ||
overlapAmount[1] = -1 * directions[1] * ((moveByY / 2) + separationBuffer); | ||
} | ||
}; | ||
/** | ||
* This method decides the separation direction of overlapping nodes | ||
* | ||
* if directions[0] = -1, then rectA goes left | ||
* if directions[0] = 1, then rectA goes right | ||
* if directions[1] = -1, then rectA goes up | ||
* if directions[1] = 1, then rectA goes down | ||
*/ | ||
IGeometry.decideDirectionsForOverlappingNodes = function (rectA, rectB, directions) | ||
@@ -86,11 +163,17 @@ { | ||
} | ||
} | ||
}; | ||
IGeometry.getIntersection2 = function (rectA, rectB, result) | ||
/** | ||
* This method calculates the intersection (clipping) points of the two | ||
* input rectangles with line segment defined by the centers of these two | ||
* rectangles. The clipping points are saved in the input double array and | ||
* whether or not the two rectangles overlap is returned. | ||
*/ | ||
IGeometry.getIntersection2 = function(rectA, rectB, result) | ||
{ | ||
//result[0-1] will contain clipPoint of rectA, result[2-3] will contain clipPoint of rectB | ||
var p1x = rectA.getCenterX(); | ||
var p1y = rectA.getCenterY(); | ||
var p2x = rectB.getCenterX(); | ||
var p2y = rectB.getCenterY(); | ||
let p1x = rectA.getCenterX(); | ||
let p1y = rectA.getCenterY(); | ||
let p2x = rectB.getCenterX(); | ||
let p2y = rectB.getCenterY(); | ||
@@ -107,25 +190,26 @@ //if two rectangles intersect, then clipping points are centers | ||
//variables for rectA | ||
var topLeftAx = rectA.getX(); | ||
var topLeftAy = rectA.getY(); | ||
var topRightAx = rectA.getRight(); | ||
var bottomLeftAx = rectA.getX(); | ||
var bottomLeftAy = rectA.getBottom(); | ||
var bottomRightAx = rectA.getRight(); | ||
var halfWidthA = rectA.getWidthHalf(); | ||
var halfHeightA = rectA.getHeightHalf(); | ||
let topLeftAx = rectA.getX(); | ||
let topLeftAy = rectA.getY(); | ||
let topRightAx = rectA.getRight(); | ||
let bottomLeftAx = rectA.getX(); | ||
let bottomLeftAy = rectA.getBottom(); | ||
let bottomRightAx = rectA.getRight(); | ||
let halfWidthA = rectA.getWidthHalf(); | ||
let halfHeightA = rectA.getHeightHalf(); | ||
//variables for rectB | ||
var topLeftBx = rectB.getX(); | ||
var topLeftBy = rectB.getY(); | ||
var topRightBx = rectB.getRight(); | ||
var bottomLeftBx = rectB.getX(); | ||
var bottomLeftBy = rectB.getBottom(); | ||
var bottomRightBx = rectB.getRight(); | ||
var halfWidthB = rectB.getWidthHalf(); | ||
var halfHeightB = rectB.getHeightHalf(); | ||
let topLeftBx = rectB.getX(); | ||
let topLeftBy = rectB.getY(); | ||
let topRightBx = rectB.getRight(); | ||
let bottomLeftBx = rectB.getX(); | ||
let bottomLeftBy = rectB.getBottom(); | ||
let bottomRightBx = rectB.getRight(); | ||
let halfWidthB = rectB.getWidthHalf(); | ||
let halfHeightB = rectB.getHeightHalf(); | ||
//flag whether clipping points are found | ||
var clipPointAFound = false; | ||
var clipPointBFound = false; | ||
let clipPointAFound = false; | ||
let clipPointBFound = false; | ||
// line is vertical | ||
if (p1x == p2x) | ||
if (p1x === p2x) | ||
{ | ||
@@ -154,3 +238,3 @@ if (p1y > p2y) | ||
// line is horizontal | ||
else if (p1y == p2y) | ||
else if (p1y === p2y) | ||
{ | ||
@@ -181,16 +265,16 @@ if (p1x > p2x) | ||
//slopes of rectA's and rectB's diagonals | ||
var slopeA = rectA.height / rectA.width; | ||
var slopeB = rectB.height / rectB.width; | ||
let slopeA = rectA.height / rectA.width; | ||
let slopeB = rectB.height / rectB.width; | ||
//slope of line between center of rectA and center of rectB | ||
var slopePrime = (p2y - p1y) / (p2x - p1x); | ||
var cardinalDirectionA; | ||
var cardinalDirectionB; | ||
var tempPointAx; | ||
var tempPointAy; | ||
var tempPointBx; | ||
var tempPointBy; | ||
let slopePrime = (p2y - p1y) / (p2x - p1x); | ||
let cardinalDirectionA; | ||
let cardinalDirectionB; | ||
let tempPointAx; | ||
let tempPointAy; | ||
let tempPointBx; | ||
let tempPointBy; | ||
//determine whether clipping point is the corner of nodeA | ||
if ((-slopeA) == slopePrime) | ||
if ((-slopeA) === slopePrime) | ||
{ | ||
@@ -210,3 +294,3 @@ if (p1x > p2x) | ||
} | ||
else if (slopeA == slopePrime) | ||
else if (slopeA === slopePrime) | ||
{ | ||
@@ -228,3 +312,3 @@ if (p1x > p2x) | ||
//determine whether clipping point is the corner of nodeB | ||
if ((-slopeB) == slopePrime) | ||
if ((-slopeB) === slopePrime) | ||
{ | ||
@@ -244,3 +328,3 @@ if (p2x > p1x) | ||
} | ||
else if (slopeB == slopePrime) | ||
else if (slopeB === slopePrime) | ||
{ | ||
@@ -272,9 +356,9 @@ if (p2x > p1x) | ||
{ | ||
cardinalDirectionA = IGeometry.getCardinalDirection(slopeA, slopePrime, 4); | ||
cardinalDirectionB = IGeometry.getCardinalDirection(slopeB, slopePrime, 2); | ||
cardinalDirectionA = this.getCardinalDirection(slopeA, slopePrime, 4); | ||
cardinalDirectionB = this.getCardinalDirection(slopeB, slopePrime, 2); | ||
} | ||
else | ||
{ | ||
cardinalDirectionA = IGeometry.getCardinalDirection(-slopeA, slopePrime, 3); | ||
cardinalDirectionB = IGeometry.getCardinalDirection(-slopeB, slopePrime, 1); | ||
cardinalDirectionA = this.getCardinalDirection(-slopeA, slopePrime, 3); | ||
cardinalDirectionB = this.getCardinalDirection(-slopeB, slopePrime, 1); | ||
} | ||
@@ -286,9 +370,9 @@ } | ||
{ | ||
cardinalDirectionA = IGeometry.getCardinalDirection(-slopeA, slopePrime, 1); | ||
cardinalDirectionB = IGeometry.getCardinalDirection(-slopeB, slopePrime, 3); | ||
cardinalDirectionA = this.getCardinalDirection(-slopeA, slopePrime, 1); | ||
cardinalDirectionB = this.getCardinalDirection(-slopeB, slopePrime, 3); | ||
} | ||
else | ||
{ | ||
cardinalDirectionA = IGeometry.getCardinalDirection(slopeA, slopePrime, 2); | ||
cardinalDirectionB = IGeometry.getCardinalDirection(slopeB, slopePrime, 4); | ||
cardinalDirectionA = this.getCardinalDirection(slopeA, slopePrime, 2); | ||
cardinalDirectionB = this.getCardinalDirection(slopeB, slopePrime, 4); | ||
} | ||
@@ -359,4 +443,11 @@ } | ||
return false; | ||
} | ||
}; | ||
/** | ||
* This method returns in which cardinal direction does input point stays | ||
* 1: North | ||
* 2: East | ||
* 3: South | ||
* 4: West | ||
*/ | ||
IGeometry.getCardinalDirection = function (slope, slopePrime, line) | ||
@@ -372,21 +463,26 @@ { | ||
} | ||
} | ||
}; | ||
IGeometry.getIntersection = function (s1, s2, f1, f2) | ||
/** | ||
* This method calculates the intersection of the two lines defined by | ||
* point pairs (s1,s2) and (f1,f2). | ||
*/ | ||
IGeometry.getIntersection = function(s1, s2, f1, f2) | ||
{ | ||
if (f2 == null) { | ||
return IGeometry.getIntersection2(s1, s2, f1); | ||
return this.getIntersection2(s1, s2, f1); | ||
} | ||
var x1 = s1.x; | ||
var y1 = s1.y; | ||
var x2 = s2.x; | ||
var y2 = s2.y; | ||
var x3 = f1.x; | ||
var y3 = f1.y; | ||
var x4 = f2.x; | ||
var y4 = f2.y; | ||
var x, y; // intersection point | ||
var a1, a2, b1, b2, c1, c2; // coefficients of line eqns. | ||
var denom; | ||
let x1 = s1.x; | ||
let y1 = s1.y; | ||
let x2 = s2.x; | ||
let y2 = s2.y; | ||
let x3 = f1.x; | ||
let y3 = f1.y; | ||
let x4 = f2.x; | ||
let y4 = f2.y; | ||
let x, y; // intersection point | ||
let a1, a2, b1, b2, c1, c2; // coefficients of line eqns. | ||
let denom; | ||
a1 = y2 - y1; | ||
@@ -402,3 +498,3 @@ b1 = x1 - x2; | ||
if (denom == 0) | ||
if (denom === 0) | ||
{ | ||
@@ -412,4 +508,64 @@ return null; | ||
return new Point(x, y); | ||
} | ||
}; | ||
/** | ||
* This method finds and returns the angle of the vector from the + x-axis | ||
* in clockwise direction (compatible w/ Java coordinate system!). | ||
*/ | ||
IGeometry.angleOfVector = function(Cx, Cy, Nx, Ny) | ||
{ | ||
let C_angle; | ||
if (Cx !== Nx) | ||
{ | ||
C_angle = Math.atan((Ny - Cy) / (Nx - Cx)); | ||
if (Nx < Cx) | ||
{ | ||
C_angle += Math.PI; | ||
} | ||
else if (Ny < Cy) | ||
{ | ||
C_angle += this.TWO_PI; | ||
} | ||
} | ||
else if (Ny < Cy) | ||
{ | ||
C_angle = this.ONE_AND_HALF_PI; // 270 degrees | ||
} | ||
else | ||
{ | ||
C_angle = this.HALF_PI; // 90 degrees | ||
} | ||
return C_angle; | ||
}; | ||
/** | ||
* This method checks whether the given two line segments (one with point | ||
* p1 and p2, the other with point p3 and p4) intersect at a point other | ||
* than these points. | ||
*/ | ||
IGeometry.doIntersect = function(p1, p2, p3, p4){ | ||
let a = p1.x; | ||
let b = p1.y; | ||
let c = p2.x; | ||
let d = p2.y; | ||
let p = p3.x; | ||
let q = p3.y; | ||
let r = p4.x; | ||
let s = p4.y; | ||
let det = (c - a) * (s - q) - (r - p) * (d - b); | ||
if (det === 0) { | ||
return false; | ||
} else { | ||
let lambda = ((s - q) * (r - a) + (p - r) * (s - b)) / det; | ||
let gamma = ((b - d) * (r - a) + (c - a) * (s - b)) / det; | ||
return (0 < lambda && lambda < 1) && (0 < gamma && gamma < 1); | ||
} | ||
}; | ||
// ----------------------------------------------------------------------------- | ||
@@ -426,2 +582,3 @@ // Section: Class Constants | ||
module.exports = IGeometry; |
@@ -20,12 +20,12 @@ function IMath() { | ||
} | ||
} | ||
}; | ||
IMath.floor = function (value) { | ||
return value < 0 ? Math.ceil(value) : Math.floor(value); | ||
} | ||
}; | ||
IMath.ceil = function (value) { | ||
return value < 0 ? Math.floor(value) : Math.ceil(value); | ||
} | ||
}; | ||
module.exports = IMath; |
@@ -0,117 +1,77 @@ | ||
/** | ||
* A classic Quicksort algorithm with Hoare's partition | ||
* - Works also on LinkedList objects | ||
* | ||
* Copyright: i-Vis Research Group, Bilkent University, 2007 - present | ||
*/ | ||
const LinkedList = require('./LinkedList.js'); | ||
function Quicksort(){ | ||
class Quicksort { | ||
constructor(A, compareFunction) { | ||
if(compareFunction !== null || compareFunction !== undefined) | ||
this.compareFunction = this._defaultCompareFunction; | ||
} | ||
let length; | ||
if( A instanceof LinkedList ) | ||
length = A.size(); | ||
else | ||
length = A.length; | ||
Quicksort.get_object_at = function(list, i){ | ||
if( list instanceof Array){ | ||
return list[i]; | ||
this._quicksort(A, 0, length - 1); | ||
} | ||
else if(list instanceof LinkedList){ | ||
return list.get_object_at(i); | ||
} | ||
}; | ||
Quicksort.set_object_at = function(list, i, value){ | ||
if( list instanceof Array){ | ||
list[i] = value; | ||
_quicksort(A, p, r){ | ||
if(p < r) { | ||
let q = this._partition(A, p, r); | ||
this._quicksort(A, p, q); | ||
this._quicksort(A, q + 1, r); | ||
} | ||
} | ||
else if(list instanceof LinkedList){ | ||
list.set_object_at(i, value); | ||
} | ||
}; | ||
Quicksort.quicksort = function(list, comparison_fn){ | ||
_partition(A, p, r){ | ||
let x = this._get(A, p); | ||
let i = p; | ||
let j = r; | ||
while(true){ | ||
while (this.compareFunction(x, this._get(A, j))) | ||
j--; | ||
while (this.compareFunction(this._get(A, i), x)) | ||
i++; | ||
// input must be an instance of LinkedList class or must be an array in order to sort | ||
if (! ( (list instanceof LinkedList) || ( list instanceof Array))){ | ||
return; | ||
if (i < j){ | ||
this._swap(A, i, j); | ||
i++; | ||
j--; | ||
} | ||
else | ||
return j; | ||
} | ||
} | ||
var comparison_function = comparison_fn; | ||
if( comparison_function === undefined){ | ||
comparison_function = Quicksort.compare; | ||
_get(object, index){ | ||
if( object instanceof LinkedList) | ||
return object.get_object_at(index); | ||
else | ||
return object[index]; | ||
} | ||
var end_index; | ||
if (list instanceof LinkedList){ | ||
end_index = list.size(); | ||
_set(object, index, value){ | ||
if( object instanceof LinkedList) | ||
object.set_object_at(index, value); | ||
else | ||
object[index] = value; | ||
} | ||
else if( list instanceof Array ){ | ||
end_index = list.length-1; | ||
} | ||
// Prevent empty lists or arrays. | ||
if (end_index >= 0){ | ||
Quicksort.quicksort_between_indices(list, 0, end_index, comparison_function); | ||
_swap(A, i, j){ | ||
let temp = this._get(A, i); | ||
this._set(A, i, this._get(A, j)); | ||
this._set(A, j, temp); | ||
} | ||
}; | ||
Quicksort.quicksort_between_indices = function(list, low, high, comparison_fn){ | ||
// input must be an instance of LinkedList class or must be an array in order to sort | ||
if (! ( (list instanceof LinkedList) || ( list instanceof Array))){ | ||
return; | ||
_defaultCompareFunction(a, b){ | ||
return b > a; | ||
} | ||
} | ||
if(comparison_fn === undefined){ | ||
comparison_fn = Quicksort.compare; | ||
} | ||
var i = low; | ||
var j = high; | ||
var middleIndex = Math.floor( ( i + j ) / 2 ); | ||
var middle = Quicksort.get_object_at(list, middleIndex); | ||
do | ||
{ | ||
while (comparison_fn(Quicksort.get_object_at(list, i), middle)){ | ||
i++; | ||
} | ||
while (comparison_fn(middle, Quicksort.get_object_at(list, j))){ | ||
j--; | ||
} | ||
if (i <= j){ | ||
var temp = Quicksort.get_object_at(list, i); | ||
Quicksort.set_object_at(list, i, Quicksort.get_object_at(list, j)); | ||
Quicksort.set_object_at(list, j, temp); | ||
i++; | ||
j--; | ||
} | ||
} while (i<=j); | ||
if( low < j ){ | ||
Quicksort.quicksort_between_indices(list, low, j, comparison_fn); | ||
} | ||
if( high > i){ | ||
Quicksort.quicksort_between_indices(list, i, high, comparison_fn); | ||
} | ||
}; | ||
// this function must be overriden for sorting different data types(e.g. string, integer etc.) | ||
Quicksort.compare = function(a,b){ | ||
return b > a; | ||
}; | ||
module.exports = Quicksort; |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
300861
7329
21
36