Skip to content

Commit d61c8a1

Browse files
Added api annotations to data structures
1 parent c715b6f commit d61c8a1

File tree

11 files changed

+2720
-2072
lines changed

11 files changed

+2720
-2072
lines changed

src.primitives/algorithms/FamilyAlignment.js

Lines changed: 232 additions & 208 deletions
Large diffs are not rendered by default.

src.primitives/algorithms/QuadTree.js

Lines changed: 252 additions & 211 deletions
Large diffs are not rendered by default.

src.primitives/algorithms/RMQ.js

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,56 +5,58 @@
55
* @returns {rmq} Returns range minimum query structure
66
*/
77
primitives.common.RMQ = function (items) {
8-
var _lookup = [];
9-
var _log2 = Math.log(2);
8+
var _lookup = [];
9+
var _log2 = Math.log(2);
1010

11-
preprocess();
11+
preprocess();
1212

13-
function preprocess() {
14-
var power;
13+
function preprocess() {
14+
var power;
1515

16-
for (var index = 0, len = items.length; index < len; index += 1) {
17-
_lookup[index] = [index];
18-
}
19-
for (power = 1, len = items.length; (1 << power) < len; power += 1) {
20-
for (index = 0; (index + (1 << power) - 1) < len; index += 1) {
21-
if (items[_lookup[index][power - 1]] < items[_lookup[index + (1 << (power - 1))][power - 1]]) {
22-
_lookup[index][power] = _lookup[index][power - 1];
23-
} else {
24-
_lookup[index][power] = _lookup[index + (1 << (power - 1))][power - 1];
25-
}
26-
}
27-
}
28-
}
16+
for (var index = 0, len = items.length; index < len; index += 1) {
17+
_lookup[index] = [index];
18+
}
19+
for (power = 1, len = items.length; (1 << power) < len; power += 1) {
20+
for (index = 0; (index + (1 << power) - 1) < len; index += 1) {
21+
if (items[_lookup[index][power - 1]] < items[_lookup[index + (1 << (power - 1))][power - 1]]) {
22+
_lookup[index][power] = _lookup[index][power - 1];
23+
} else {
24+
_lookup[index][power] = _lookup[index + (1 << (power - 1))][power - 1];
25+
}
26+
}
27+
}
28+
}
2929

3030
/**
3131
* Returns index of minimum item for the given range of items
32+
*
3233
* @param {number} from The left margin index
3334
* @param {number} to The right margin index
3435
* @returns {number} Returns index of the minimum item
3536
*/
36-
function getRangeMinimumIndex(from, to) {
37-
var power = Math.floor(Math.log(to - from + 1) / _log2);
37+
function getRangeMinimumIndex(from, to) {
38+
var power = Math.floor(Math.log(to - from + 1) / _log2);
3839

39-
if (items[_lookup[from][power]] <= items[_lookup[to - (1 << power) + 1][power]]) {
40-
return _lookup[from][power];
41-
} else {
42-
return _lookup[to - (1 << power) + 1][power];
43-
}
44-
}
40+
if (items[_lookup[from][power]] <= items[_lookup[to - (1 << power) + 1][power]]) {
41+
return _lookup[from][power];
42+
} else {
43+
return _lookup[to - (1 << power) + 1][power];
44+
}
45+
}
4546

4647
/**
4748
* Return minimum value for the given range
49+
*
4850
* @param {number} from The left index of the range
4951
* @param {number} to The right index of the range
5052
* @returns {number} Returns minimum value in the range
5153
*/
52-
function getRangeMinimum(from, to) {
53-
return items[getRangeMinimumIndex(from, to)];
54-
}
54+
function getRangeMinimum(from, to) {
55+
return items[getRangeMinimumIndex(from, to)];
56+
}
5557

56-
return {
57-
getRangeMinimumIndex: getRangeMinimumIndex,
58-
getRangeMinimum: getRangeMinimum
59-
};
58+
return {
59+
getRangeMinimumIndex: getRangeMinimumIndex,
60+
getRangeMinimum: getRangeMinimum
61+
};
6062
};
Lines changed: 125 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,140 @@
1+
/**
2+
* Create spatial index structure. It uses collection of sizes to distribute
3+
* rectangles into buckets of similar size elements. Elements of the same bucket
4+
* are aproximated to points. The search of rectangles is transformed to search of points
5+
* within given range plus offset for maximum linear rectangle size.
6+
*
7+
* @returns {SpatialIndex} Returns spacial index data structure.
8+
*/
19
primitives.common.SpatialIndex = function (sizes) {
2-
var _buckets = [];
10+
var _buckets = [];
311

4-
sizes.sort(function (a, b) { return a - b;});
12+
sizes.sort(function (a, b) { return a - b; });
513

6-
switch (sizes.length) {
7-
case 0:
8-
_buckets.push(new Bucket(0, 1000000));
9-
break;
10-
case 1:
11-
var size1 = sizes[0];
12-
_buckets.push(new Bucket(0, size1));
13-
break;
14-
case 2:
15-
size1 = sizes[0];
16-
var size2 = sizes[1];
17-
if (size2 > size1 * 2) {
18-
_buckets.push(new Bucket(0, size1));
19-
_buckets.push(new Bucket(size1, size2));
20-
} else {
21-
_buckets.push(new Bucket(0, size2));
22-
}
23-
break;
24-
default:
25-
var breaks = primitives.common.getLiniarBreaks(sizes);
26-
var minimum = 0;
27-
for (var index = 0; index < breaks.length; index += 1) {
28-
var maximum = sizes[breaks[index]];
29-
_buckets.push(new Bucket(minimum, maximum));
30-
minimum = maximum;
31-
}
32-
break;
33-
}
14+
switch (sizes.length) {
15+
case 0:
16+
_buckets.push(new Bucket(0, 1000000));
17+
break;
18+
case 1:
19+
var size1 = sizes[0];
20+
_buckets.push(new Bucket(0, size1));
21+
break;
22+
case 2:
23+
size1 = sizes[0];
24+
var size2 = sizes[1];
25+
if (size2 > size1 * 2) {
26+
_buckets.push(new Bucket(0, size1));
27+
_buckets.push(new Bucket(size1, size2));
28+
} else {
29+
_buckets.push(new Bucket(0, size2));
30+
}
31+
break;
32+
default:
33+
var breaks = primitives.common.getLiniarBreaks(sizes);
34+
var minimum = 0;
35+
for (var index = 0; index < breaks.length; index += 1) {
36+
var maximum = sizes[breaks[index]];
37+
_buckets.push(new Bucket(minimum, maximum));
38+
minimum = maximum;
39+
}
40+
break;
41+
}
3442

35-
function Bucket(minimum, maximum) {
36-
this.minimum = minimum;
37-
this.maximum = maximum;
38-
this.quadTree = primitives.common.QuadTree(maximum * 2);
39-
}
43+
function Bucket(minimum, maximum) {
44+
this.minimum = minimum;
45+
this.maximum = maximum;
46+
this.quadTree = primitives.common.QuadTree(maximum * 2);
47+
}
4048

41-
function addRect(rect) {
42-
var size = Math.max(rect.width, rect.height);
43-
var point = rect.centerPoint();
49+
/**
50+
* Adds rectangle to spacial index
51+
* @param {Rect} rect Rectangle
52+
*/
53+
function addRect(rect) {
54+
var size = Math.max(rect.width, rect.height);
55+
var point = rect.centerPoint();
4456

45-
for (var index = 0, len = _buckets.length; index < len; index += 1) {
46-
var bucket = _buckets[index];
57+
for (var index = 0, len = _buckets.length; index < len; index += 1) {
58+
var bucket = _buckets[index];
4759

48-
if (size <= bucket.maximum || index == len - 1) {
49-
point.context = rect;
50-
bucket.quadTree.addPoint(point);
51-
break;
52-
}
53-
}
54-
}
60+
if (size <= bucket.maximum || index == len - 1) {
61+
point.context = rect;
62+
bucket.quadTree.addPoint(point);
63+
break;
64+
}
65+
}
66+
}
5567

56-
function loopArea(thisArg, rect, onItem) { // onItem = function(itemid) {}
57-
if (onItem != null) {
58-
for (var index = 0, len = _buckets.length; index < len; index += 1) {
59-
var bucket = _buckets[index];
60-
var bucketRect = new primitives.common.Rect(rect);
61-
bucketRect.offset(bucket.maximum / 2.0);
62-
bucket.quadTree.loopArea(this, bucketRect, function (point) {
63-
var pointRect = point.context;
68+
/**
69+
* Callback function for iteration of spacial index rectangles
70+
*
71+
* @callback onSpatialIndexItemCallback
72+
* @param {React} rect Rectangle
73+
* @returns {boolean} Returns true to break iteration process.
74+
*/
6475

65-
if (rect.overlaps(pointRect)) {
66-
return onItem.call(thisArg, pointRect);
67-
}
68-
});
69-
}
70-
}
71-
}
76+
/**
77+
* Loops rectangular area of spacial index
78+
*
79+
* @param {object} thisArg The callback function invocation context
80+
* @param {Rect}} rect Rectangular search area
81+
* @param {onSpatialIndexItemCallback} onItem Callback function to call for every rectangle intersecting given rectangular search area
82+
*/
83+
function loopArea(thisArg, rect, onItem) { // onItem = function(itemid) {}
84+
if (onItem != null) {
85+
for (var index = 0, len = _buckets.length; index < len; index += 1) {
86+
var bucket = _buckets[index];
87+
var bucketRect = new primitives.common.Rect(rect);
88+
bucketRect.offset(bucket.maximum / 2.0);
89+
bucket.quadTree.loopArea(this, bucketRect, function (point) {
90+
var pointRect = point.context;
7291

73-
function validate() {
74-
var result = true;
75-
for (var index = 0, len = _buckets.length; index < len; index += 1) {
76-
var bucket = _buckets[index];
92+
if (rect.overlaps(pointRect)) {
93+
return onItem.call(thisArg, pointRect);
94+
}
95+
});
96+
}
97+
}
98+
}
7799

78-
result = result && bucket.quadTree.validate();
79-
}
80-
return result;
81-
}
100+
/**
101+
* Validates internal data consistency of spacial index data structure
102+
*
103+
* @returns {boolean} Returns true if structure pass validation
104+
*/
105+
function validate() {
106+
var result = true;
107+
for (var index = 0, len = _buckets.length; index < len; index += 1) {
108+
var bucket = _buckets[index];
82109

83-
function getPositions(selection) {
84-
var result = [];
85-
for (var index = 0, len = _buckets.length; index < len; index += 1) {
86-
var bucket = _buckets[index];
110+
result = result && bucket.quadTree.validate();
111+
}
112+
return result;
113+
}
87114

88-
result = result.concat(bucket.quadTree.getPositions(selection));
89-
}
90-
return result;
91-
}
115+
/**
116+
* Returns collection of quadrands created in spacial index
117+
* Quadrants exists only when elements exists in them.
118+
* This method is used for visual debugging of the structure.
119+
*
120+
* @param {React} selection Rectangular test area to highlight quadrants
121+
* @returns {Rect[]} Returns collection of available quadrants.
122+
* Quadrants containing points within selection area have context.highlight property set to true.
123+
*/
124+
function getPositions(selection) {
125+
var result = [];
126+
for (var index = 0, len = _buckets.length; index < len; index += 1) {
127+
var bucket = _buckets[index];
92128

93-
return {
94-
addRect: addRect,
95-
loopArea: loopArea,
96-
validate: validate,
97-
getPositions: getPositions
98-
};
129+
result = result.concat(bucket.quadTree.getPositions(selection));
130+
}
131+
return result;
132+
}
133+
134+
return {
135+
addRect: addRect,
136+
loopArea: loopArea,
137+
validate: validate,
138+
getPositions: getPositions
139+
};
99140
};

0 commit comments

Comments
 (0)