Browse Source

Pull request #3312: KERNEL-14012 feat: core/structure文件夹

Merge in VISUAL/fineui from ~DAILER/fineui:es6 to es6

* commit 'c4184571d3c5b808fb3231add275aa356ffdf513':
  KERNEL-14012 feat: core/structure文件夹
  KERNEL-14012 feat: core/structure文件夹
  KERNEL-14012 feat: core/structure文件夹
es6
Dailer-刘荣歆 2 years ago
parent
commit
929649567a
  1. 12
      src/core/index.js
  2. 4036
      src/core/structure/aes.js
  3. 103
      src/core/structure/aspect.js
  4. 216
      src/core/structure/base64.js
  5. 47
      src/core/structure/cache.js
  6. 212
      src/core/structure/cellSizeAndPositionManager.js
  7. 168
      src/core/structure/heap.js
  8. 13
      src/core/structure/index.js
  9. 116
      src/core/structure/linkedHashMap.js
  10. 38
      src/core/structure/lru.js
  11. 291
      src/core/structure/prefixIntervalTree.js
  12. 143
      src/core/structure/queue.js
  13. 121
      src/core/structure/sectionManager.js
  14. 934
      src/core/structure/tree.js
  15. 61
      src/core/structure/vector.js

12
src/core/index.js

@ -1,4 +1,3 @@
import * as base from "./2.base";
import * as ob from "./3.ob";
import * as widget from "./4.widget";
@ -7,10 +6,11 @@ import * as action from "./action";
import * as behavior from "./behavior";
import * as controllers from "./controller";
import * as func from "./func";
import { StyleLoaderManager } from "./loader/loader.style";
import * as structure from "./structure";
import {StyleLoaderManager} from "./loader/loader.style";
import "./h";
import { ShowListener } from "./listener/listener.show";
import { shortcut } from "./decorator";
import {ShowListener} from "./listener/listener.show";
import {shortcut} from "./decorator";
export * from "./2.base";
export * from "./3.ob";
@ -20,6 +20,7 @@ export * from "./action";
export * from "./behavior";
export * from "./controller";
export * from "./func";
export * from "./structure";
// 有了后删掉
export const emptyFn = () => { }
@ -28,7 +29,7 @@ export {
StyleLoaderManager,
ShowListener,
shortcut,
}
};
Object.assign(BI, {
...base,
@ -42,4 +43,5 @@ Object.assign(BI, {
...func,
StyleLoaderManager,
ShowListener,
...structure,
});

4036
src/core/structure/aes.js

File diff suppressed because it is too large Load Diff

103
src/core/structure/aspect.js

@ -1,63 +1,58 @@
!(function () {
function aspect (type) {
return function (target, methodName, advice) {
var exist = target[methodName],
dispatcher;
if (!exist || exist.target != target) {
dispatcher = target[methodName] = function () {
// before methods
var beforeArr = dispatcher.before;
var args = arguments, next;
for (var l = beforeArr.length; l--;) {
next = beforeArr[l].advice.apply(this, args);
if (next === false) {
return false;
}
args = next || args;
}
// target method
var rs = dispatcher.method.apply(this, args);
// after methods
var afterArr = dispatcher.after;
for (var i = 0, ii = afterArr.length; i < ii; i++) {
next = afterArr[i].advice.call(this, rs, args);
if (rs === false) {
return false;
}
args = next || args;
function _aspect(type) {
return function (target, methodName, advice) {
let exist = target[methodName],
dispatcher;
if (!exist || exist.target != target) {
dispatcher = target[methodName] = function () {
// before methods
let beforeArr = dispatcher.before;
let args = arguments, next;
for (let l = beforeArr.length; l--;) {
next = beforeArr[l].advice.apply(this, args);
if (next === false) {
return false;
}
return rs;
};
dispatcher.before = [];
dispatcher.after = [];
if (exist) {
dispatcher.method = exist;
args = next || args;
}
dispatcher.target = target;
}
var aspectArr = (dispatcher || exist)[type];
var obj = {
advice: advice,
_index: aspectArr.length,
remove: function () {
aspectArr.splice(this._index, 1);
// target method
let rs = dispatcher.method.apply(this, args);
// after methods
let afterArr = dispatcher.after;
for (let i = 0, ii = afterArr.length; i < ii; i++) {
next = afterArr[i].advice.call(this, rs, args);
if (rs === false) {
return false;
}
args = next || args;
}
return rs;
};
aspectArr.push(obj);
return obj;
dispatcher.before = [];
dispatcher.after = [];
if (exist) {
dispatcher.method = exist;
}
dispatcher.target = target;
}
let aspectArr = (dispatcher || exist)[type];
let obj = {
advice: advice,
_index: aspectArr.length,
remove: function () {
aspectArr.splice(this._index, 1);
},
};
}
aspectArr.push(obj);
BI.aspect = {
before: aspect("before"),
after: aspect("after")
return obj;
};
}
return BI.aspect;
})();
export const aspect = {
before: _aspect("before"),
after: _aspect("after"),
};

216
src/core/structure/base64.js

@ -1,130 +1,132 @@
const _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
!(function () {
var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
// private method for UTF-8 encoding
const _utf8_encode = function (string) {
string = string.replace(/\r\n/g, "\n");
let utftext = "";
for (let n = 0; n < string.length; n++) {
// private method for UTF-8 encoding
var _utf8_encode = function (string) {
string = string.replace(/\r\n/g, "\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if ((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
const c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if ((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
return utftext;
};
// private method for UTF-8 decoding
var _utf8_decode = function (utftext) {
var string = "";
var i = 0;
var c = 0, c3 = 0, c2 = 0;
while (i < utftext.length) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
} else if ((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i + 1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = utftext.charCodeAt(i + 1);
c3 = utftext.charCodeAt(i + 2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return utftext;
};
// private method for UTF-8 decoding
const _utf8_decode = function (utftext) {
let string = "";
let i = 0;
let c = 0, c3 = 0, c2 = 0;
while (i < utftext.length) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
} else if ((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i + 1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = utftext.charCodeAt(i + 1);
c3 = utftext.charCodeAt(i + 2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
return string;
};
BI._.extend(BI, {
encode: function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = _utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
}
return string;
};
/**
* base64 encode
* @param input
* @returns {string}
*/
export function encode(input) {
let output = "";
let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
let i = 0;
input = _utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
}
}
return output;
},
return output;
}
// public method for decoding
decode: function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
/**
* base64 decode
* @param input
* @returns {string}
*/
export function decode(input) {
let output = "";
let chr1, chr2, chr3;
let enc1, enc2, enc3, enc4;
let i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
while (i < input.length) {
enc1 = _keyStr.indexOf(input.charAt(i++));
enc2 = _keyStr.indexOf(input.charAt(i++));
enc3 = _keyStr.indexOf(input.charAt(i++));
enc4 = _keyStr.indexOf(input.charAt(i++));
enc1 = _keyStr.indexOf(input.charAt(i++));
enc2 = _keyStr.indexOf(input.charAt(i++));
enc3 = _keyStr.indexOf(input.charAt(i++));
enc4 = _keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
}
output = _utf8_decode(output);
output = _utf8_decode(output);
return output;
return output;
}
});
})();
}

47
src/core/structure/cache.js

@ -1,43 +1,42 @@
BI.Cache = {
export const Cache = {
_prefix: "bi",
setUsername: function (username) {
localStorage.setItem(BI.Cache._prefix + ".username", (username + "" || "").toUpperCase());
localStorage.setItem(Cache._prefix + ".username", (username + "" || "").toUpperCase());
},
getUsername: function () {
return localStorage.getItem(BI.Cache._prefix + ".username") || "";
return localStorage.getItem(Cache._prefix + ".username") || "";
},
_getKeyPrefix: function () {
return BI.Cache.getUsername() + "." + BI.Cache._prefix + ".";
return Cache.getUsername() + "." + Cache._prefix + ".";
},
_generateKey: function (key) {
return BI.Cache._getKeyPrefix() + (key || "");
return Cache._getKeyPrefix() + (key || "");
},
getItem: function (key) {
return localStorage.getItem(BI.Cache._generateKey(key));
return localStorage.getItem(Cache._generateKey(key));
},
setItem: function (key, value) {
localStorage.setItem(BI.Cache._generateKey(key), value);
localStorage.setItem(Cache._generateKey(key), value);
},
removeItem: function (key) {
localStorage.removeItem(BI.Cache._generateKey(key));
localStorage.removeItem(Cache._generateKey(key));
},
clear: function () {
for (var i = localStorage.length; i >= 0; i--) {
var key = localStorage.key(i);
for (let i = localStorage.length; i >= 0; i--) {
const key = localStorage.key(i);
if (key) {
if (key.indexOf(BI.Cache._getKeyPrefix()) === 0) {
if (key.indexOf(Cache._getKeyPrefix()) === 0) {
localStorage.removeItem(key);
}
}
}
},
keys: function () {
var result = [];
for (var i = localStorage.length; i >= 0; i--) {
var key = localStorage.key(i);
const result = [];
for (let i = localStorage.length; i >= 0; i--) {
const key = localStorage.key(i);
if (key) {
var prefix = BI.Cache._getKeyPrefix();
const prefix = Cache._getKeyPrefix();
if (key.indexOf(prefix) === 0) {
result[result.length] = key.substring(prefix.length);
}
@ -47,10 +46,10 @@ BI.Cache = {
},
addCookie: function (name, value, path, expiresHours) {
var cookieString = name + "=" + encodeURI(value);
let cookieString = name + "=" + encodeURI(value);
// 判断是否设置过期时间
if (expiresHours && expiresHours > 0) {
var date = new Date();
const date = new Date();
// expires是标准GMT格式时间,应该使用时间戳作为起始时间
date.setTime(date.getTime() + expiresHours * 3600 * 1000);
cookieString = cookieString + "; expires=" + date.toUTCString();
@ -61,17 +60,19 @@ BI.Cache = {
document.cookie = cookieString;
},
getCookie: function (name) {
var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
if (arr = document.cookie.match(reg)) {return decodeURI(arr[2]);}
let arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
if (arr = document.cookie.match(reg)) {
return decodeURI(arr[2]);
}
return null;
},
deleteCookie: function (name, path) {
var date = new Date();
const date = new Date();
date.setTime(date.getTime() - 10000);
var cookieString = name + "=v; expires=" + date.toUTCString();
let cookieString = name + "=v; expires=" + date.toUTCString();
if (path) {
cookieString = cookieString + "; path=" + path;
}
document.cookie = cookieString;
}
},
};

212
src/core/structure/cellSizeAndPositionManager.js

@ -1,40 +1,40 @@
BI.CellSizeAndPositionManager = function (cellCount, cellSizeGetter, estimatedCellSize) {
this._cellSizeGetter = cellSizeGetter;
this._cellCount = cellCount;
this._estimatedCellSize = estimatedCellSize;
this._cellSizeAndPositionData = {};
this._lastMeasuredIndex = -1;
};
BI.CellSizeAndPositionManager.prototype = {
constructor: BI.CellSizeAndPositionManager,
configure: function (cellCount, estimatedCellSize) {
export class CellSizeAndPositionManager {
constructor(cellCount, cellSizeGetter, estimatedCellSize) {
this._cellSizeGetter = cellSizeGetter;
this._cellCount = cellCount;
this._estimatedCellSize = estimatedCellSize;
},
this._cellSizeAndPositionData = {};
this._lastMeasuredIndex = -1;
}
getCellCount: function () {
configure(cellCount, estimatedCellSize) {
this._cellCount = cellCount;
this._estimatedCellSize = estimatedCellSize;
}
getCellCount() {
return this._cellCount;
},
}
getEstimatedCellSize: function () {
getEstimatedCellSize() {
return this._estimatedCellSize;
},
}
getLastMeasuredIndex: function () {
getLastMeasuredIndex() {
return this._lastMeasuredIndex;
},
}
getSizeAndPositionOfCell: function (index) {
getSizeAndPositionOfCell(index) {
if (index < 0 || index >= this._cellCount) {
return;
}
if (index > this._lastMeasuredIndex) {
var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
var offset = lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size;
const lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
let offset = lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size;
for (var i = this._lastMeasuredIndex + 1; i <= index; i++) {
var size = this._cellSizeGetter(i);
for (let i = this._lastMeasuredIndex + 1; i <= index; i++) {
const size = this._cellSizeGetter(i);
if (size == null || isNaN(size)) {
continue;
@ -42,7 +42,7 @@ BI.CellSizeAndPositionManager.prototype = {
this._cellSizeAndPositionData[i] = {
offset: offset,
size: size
size: size,
};
offset += size;
@ -51,28 +51,28 @@ BI.CellSizeAndPositionManager.prototype = {
this._lastMeasuredIndex = index;
}
return this._cellSizeAndPositionData[index];
},
}
getSizeAndPositionOfLastMeasuredCell: function () {
getSizeAndPositionOfLastMeasuredCell() {
return this._lastMeasuredIndex >= 0
? this._cellSizeAndPositionData[this._lastMeasuredIndex]
: {
offset: 0,
size: 0
size: 0,
};
},
}
getTotalSize: function () {
var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
getTotalSize() {
const lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
return lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size + (this._cellCount - this._lastMeasuredIndex - 1) * this._estimatedCellSize;
},
}
getUpdatedOffsetForIndex: function (align, containerSize, currentOffset, targetIndex) {
var datum = this.getSizeAndPositionOfCell(targetIndex);
var maxOffset = datum.offset;
var minOffset = maxOffset - containerSize + datum.size;
getUpdatedOffsetForIndex(align, containerSize, currentOffset, targetIndex) {
const datum = this.getSizeAndPositionOfCell(targetIndex);
const maxOffset = datum.offset;
const minOffset = maxOffset - containerSize + datum.size;
var idealOffset;
let idealOffset;
switch (align) {
case "start":
@ -89,25 +89,25 @@ BI.CellSizeAndPositionManager.prototype = {
break;
}
var totalSize = this.getTotalSize();
const totalSize = this.getTotalSize();
return Math.max(0, Math.min(totalSize - containerSize, idealOffset));
},
}
getVisibleCellRange: function (containerSize, offset) {
var totalSize = this.getTotalSize();
getVisibleCellRange(containerSize, offset) {
const totalSize = this.getTotalSize();
if (totalSize === 0) {
return {};
}
var maxOffset = offset + containerSize;
var start = this._findNearestCell(offset);
const maxOffset = offset + containerSize;
const start = this._findNearestCell(offset);
var datum = this.getSizeAndPositionOfCell(start);
const datum = this.getSizeAndPositionOfCell(start);
offset = datum.offset + datum.size;
var stop = start;
let stop = start;
while (offset < maxOffset && stop < this._cellCount - 1) {
stop++;
@ -116,17 +116,17 @@ BI.CellSizeAndPositionManager.prototype = {
return {
start: start,
stop: stop
stop: stop,
};
},
}
resetCell: function (index) {
resetCell(index) {
this._lastMeasuredIndex = Math.min(this._lastMeasuredIndex, index - 1);
},
}
_binarySearch: function (high, low, offset) {
var middle;
var currentOffset;
_binarySearch(high, low, offset) {
let middle;
let currentOffset;
while (low <= high) {
middle = low + Math.floor((high - low) / 2);
@ -144,10 +144,10 @@ BI.CellSizeAndPositionManager.prototype = {
if (low > 0) {
return low - 1;
}
},
}
_exponentialSearch: function (index, offset) {
var interval = 1;
_exponentialSearch(index, offset) {
let interval = 1;
while (index < this._cellCount && this.getSizeAndPositionOfCell(index).offset < offset) {
index += interval;
@ -155,117 +155,115 @@ BI.CellSizeAndPositionManager.prototype = {
}
return this._binarySearch(Math.min(index, this._cellCount - 1), Math.floor(index / 2), offset);
},
}
_findNearestCell: function (offset) {
_findNearestCell(offset) {
if (isNaN(offset)) {
return;
}
offset = Math.max(0, offset);
var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
var lastMeasuredIndex = Math.max(0, this._lastMeasuredIndex);
const lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
const lastMeasuredIndex = Math.max(0, this._lastMeasuredIndex);
if (lastMeasuredCellSizeAndPosition.offset >= offset) {
return this._binarySearch(lastMeasuredIndex, 0, offset);
}
return this._exponentialSearch(lastMeasuredIndex, offset);
}
};
BI.ScalingCellSizeAndPositionManager = function (cellCount, cellSizeGetter, estimatedCellSize, maxScrollSize) {
this._cellSizeAndPositionManager = new BI.CellSizeAndPositionManager(cellCount, cellSizeGetter, estimatedCellSize);
this._maxScrollSize = maxScrollSize || 10000000;
};
}
}
BI.ScalingCellSizeAndPositionManager.prototype = {
constructor: BI.ScalingCellSizeAndPositionManager,
export class ScalingCellSizeAndPositionManager {
constructor(cellCount, cellSizeGetter, estimatedCellSize, maxScrollSize) {
this._cellSizeAndPositionManager = new CellSizeAndPositionManager(cellCount, cellSizeGetter, estimatedCellSize);
this._maxScrollSize = maxScrollSize || 10000000;
}
configure: function () {
configure() {
this._cellSizeAndPositionManager.configure.apply(this._cellSizeAndPositionManager, arguments);
},
}
getCellCount: function () {
getCellCount() {
return this._cellSizeAndPositionManager.getCellCount();
},
}
getEstimatedCellSize: function () {
getEstimatedCellSize() {
return this._cellSizeAndPositionManager.getEstimatedCellSize();
},
}
getLastMeasuredIndex: function () {
getLastMeasuredIndex() {
return this._cellSizeAndPositionManager.getLastMeasuredIndex();
},
}
getOffsetAdjustment: function (containerSize, offset) {
var totalSize = this._cellSizeAndPositionManager.getTotalSize();
var safeTotalSize = this.getTotalSize();
var offsetPercentage = this._getOffsetPercentage(containerSize, offset, safeTotalSize);
getOffsetAdjustment(containerSize, offset) {
const totalSize = this._cellSizeAndPositionManager.getTotalSize();
const safeTotalSize = this.getTotalSize();
const offsetPercentage = this._getOffsetPercentage(containerSize, offset, safeTotalSize);
return Math.round(offsetPercentage * (safeTotalSize - totalSize));
},
}
getSizeAndPositionOfCell: function (index) {
getSizeAndPositionOfCell(index) {
return this._cellSizeAndPositionManager.getSizeAndPositionOfCell(index);
},
}
getSizeAndPositionOfLastMeasuredCell: function () {
getSizeAndPositionOfLastMeasuredCell() {
return this._cellSizeAndPositionManager.getSizeAndPositionOfLastMeasuredCell();
},
}
getTotalSize: function () {
getTotalSize() {
return Math.min(this._maxScrollSize, this._cellSizeAndPositionManager.getTotalSize());
},
}
getUpdatedOffsetForIndex: function (align, containerSize, currentOffset, targetIndex) {
getUpdatedOffsetForIndex(align, containerSize, currentOffset, targetIndex) {
currentOffset = this._safeOffsetToOffset(containerSize, currentOffset);
var offset = this._cellSizeAndPositionManager.getUpdatedOffsetForIndex(align, containerSize, currentOffset, targetIndex);
const offset = this._cellSizeAndPositionManager.getUpdatedOffsetForIndex(align, containerSize, currentOffset, targetIndex);
return this._offsetToSafeOffset(containerSize, offset);
},
}
getVisibleCellRange: function (containerSize, offset) {
getVisibleCellRange(containerSize, offset) {
offset = this._safeOffsetToOffset(containerSize, offset);
return this._cellSizeAndPositionManager.getVisibleCellRange(containerSize, offset);
},
}
resetCell: function (index) {
resetCell(index) {
this._cellSizeAndPositionManager.resetCell(index);
},
}
_getOffsetPercentage: function (containerSize, offset, totalSize) {
_getOffsetPercentage(containerSize, offset, totalSize) {
return totalSize <= containerSize
? 0
: offset / (totalSize - containerSize);
},
}
_offsetToSafeOffset: function (containerSize, offset) {
var totalSize = this._cellSizeAndPositionManager.getTotalSize();
var safeTotalSize = this.getTotalSize();
_offsetToSafeOffset(containerSize, offset) {
const totalSize = this._cellSizeAndPositionManager.getTotalSize();
const safeTotalSize = this.getTotalSize();
if (totalSize === safeTotalSize) {
return offset;
}
var offsetPercentage = this._getOffsetPercentage(containerSize, offset, totalSize);
const offsetPercentage = this._getOffsetPercentage(containerSize, offset, totalSize);
return Math.round(offsetPercentage * (safeTotalSize - containerSize));
},
_safeOffsetToOffset: function (containerSize, offset) {
var totalSize = this._cellSizeAndPositionManager.getTotalSize();
var safeTotalSize = this.getTotalSize();
}
_safeOffsetToOffset(containerSize, offset) {
const totalSize = this._cellSizeAndPositionManager.getTotalSize();
const safeTotalSize = this.getTotalSize();
if (totalSize === safeTotalSize) {
return offset;
}
var offsetPercentage = this._getOffsetPercentage(containerSize, offset, safeTotalSize);
const offsetPercentage = this._getOffsetPercentage(containerSize, offset, safeTotalSize);
return Math.round(offsetPercentage * (totalSize - containerSize));
}
};
}

168
src/core/structure/heap.js

@ -1,115 +1,111 @@
function defaultComparator(a, b) {
return a < b;
}
(function () {
function defaultComparator (a, b) {
return a < b;
}
BI.Heap = function (items, comparator) {
export class Heap {
constructor(items, comparator) {
this._items = items || [];
this._size = this._items.length;
this._comparator = comparator || defaultComparator;
this._heapify();
};
BI.Heap.prototype = {
constructor: BI.Heap,
empty: function () {
return this._size === 0;
},
}
pop: function () {
if (this._size === 0) {
return;
}
empty() {
return this._size === 0;
}
var elt = this._items[0];
pop() {
if (this._size === 0) {
return;
}
var lastElt = this._items.pop();
this._size--;
const elt = this._items[0];
if (this._size > 0) {
this._items[0] = lastElt;
this._sinkDown(0);
}
const lastElt = this._items.pop();
this._size--;
return elt;
},
if (this._size > 0) {
this._items[0] = lastElt;
this._sinkDown(0);
}
push: function (item) {
this._items[this._size++] = item;
this._bubbleUp(this._size - 1);
},
return elt;
}
size: function () {
return this._size;
},
push(item) {
this._items[this._size++] = item;
this._bubbleUp(this._size - 1);
}
peek: function () {
if (this._size === 0) {
return;
}
size() {
return this._size;
}
return this._items[0];
},
peek() {
if (this._size === 0) {
return;
}
_heapify: function () {
for (var index = Math.floor((this._size + 1) / 2); index >= 0; index--) {
this._sinkDown(index);
}
},
return this._items[0];
}
_bubbleUp: function (index) {
var elt = this._items[index];
while (index > 0) {
var parentIndex = Math.floor((index + 1) / 2) - 1;
var parentElt = this._items[parentIndex];
_heapify() {
for (let index = Math.floor((this._size + 1) / 2); index >= 0; index--) {
this._sinkDown(index);
}
}
// if parentElt < elt, stop
if (this._comparator(parentElt, elt)) {
return;
}
_bubbleUp(index) {
const elt = this._items[index];
while (index > 0) {
const parentIndex = Math.floor((index + 1) / 2) - 1;
const parentElt = this._items[parentIndex];
// swap
this._items[parentIndex] = elt;
this._items[index] = parentElt;
index = parentIndex;
// if parentElt < elt, stop
if (this._comparator(parentElt, elt)) {
return;
}
},
_sinkDown: function (index) {
var elt = this._items[index];
// swap
this._items[parentIndex] = elt;
this._items[index] = parentElt;
index = parentIndex;
}
}
while (true) {
var leftChildIndex = 2 * (index + 1) - 1;
var rightChildIndex = 2 * (index + 1);
var swapIndex = -1;
_sinkDown(index) {
const elt = this._items[index];
if (leftChildIndex < this._size) {
var leftChild = this._items[leftChildIndex];
if (this._comparator(leftChild, elt)) {
swapIndex = leftChildIndex;
}
}
while (true) {
const leftChildIndex = 2 * (index + 1) - 1;
const rightChildIndex = 2 * (index + 1);
let swapIndex = -1;
if (rightChildIndex < this._size) {
var rightChild = this._items[rightChildIndex];
if (this._comparator(rightChild, elt)) {
if (swapIndex === -1 ||
this._comparator(rightChild, this._items[swapIndex])) {
swapIndex = rightChildIndex;
}
}
if (leftChildIndex < this._size) {
const leftChild = this._items[leftChildIndex];
if (this._comparator(leftChild, elt)) {
swapIndex = leftChildIndex;
}
}
// if we don't have a swap, stop
if (swapIndex === -1) {
return;
if (rightChildIndex < this._size) {
const rightChild = this._items[rightChildIndex];
if (this._comparator(rightChild, elt)) {
if (swapIndex === -1 ||
this._comparator(rightChild, this._items[swapIndex])) {
swapIndex = rightChildIndex;
}
}
}
this._items[index] = this._items[swapIndex];
this._items[swapIndex] = elt;
index = swapIndex;
// if we don't have a swap, stop
if (swapIndex === -1) {
return;
}
this._items[index] = this._items[swapIndex];
this._items[swapIndex] = elt;
index = swapIndex;
}
};
})();
}
}

13
src/core/structure/index.js

@ -0,0 +1,13 @@
export * from "./aes";
export * from "./aspect";
export * from "./base64";
export * from "./cache";
export * from "./cellSizeAndPositionManager";
export * from "./heap";
export * from "./linkedHashMap";
export * from "./lru";
export * from "./prefixIntervalTree";
export * from "./queue";
export * from "./sectionManager";
export * from "./tree";
export * from "./vector";

116
src/core/structure/linkedHashMap.js

@ -1,72 +1,66 @@
!(function () {
BI.LinkHashMap = function () {
export class LinkHashMap {
constructor() {
this.array = [];
this.map = {};
};
BI.LinkHashMap.prototype = {
constructor: BI.LinkHashMap,
has: function (key) {
if (key in this.map) {
return true;
}
return false;
},
add: function (key, value) {
if (typeof key === "undefined") {
return;
}
if (key in this.map) {
this.map[key] = value;
} else {
this.array.push(key);
this.map[key] = value;
}
},
}
remove: function (key) {
if (key in this.map) {
delete this.map[key];
for (var i = 0; i < this.array.length; i++) {
if (this.array[i] == key) {
this.array.splice(i, 1);
break;
}
}
}
},
has(key) {
return key in this.map;
}
size: function () {
return this.array.length;
},
add(key, value) {
if (typeof key === "undefined") {
return;
}
if (key in this.map) {
this.map[key] = value;
} else {
this.array.push(key);
this.map[key] = value;
}
}
each: function (fn, scope) {
var scope = scope || window;
var fn = fn || null;
if (fn == null || typeof (fn) !== "function") {
return;
}
for (var i = 0; i < this.array.length; i++) {
var key = this.array[i];
var value = this.map[key];
var re = fn.call(scope, key, value, i, this.array, this.map);
if (re == false) {
remove(key) {
if (key in this.map) {
delete this.map[key];
for (let i = 0; i < this.array.length; i++) {
if (this.array[i] == key) {
this.array.splice(i, 1);
break;
}
}
},
}
}
get: function (key) {
return this.map[key];
},
size() {
return this.array.length;
}
toArray: function () {
var array = [];
this.each(function (key, value) {
array.push(value);
});
return array;
each(fn, scope) {
scope = scope || window;
fn = fn || null;
if (fn == null || typeof (fn) !== "function") {
return;
}
};
})();
for (let i = 0; i < this.array.length; i++) {
const key = this.array[i];
const value = this.map[key];
const re = fn.call(scope, key, value, i, this.array, this.map);
if (re == false) {
break;
}
}
}
get(key) {
return this.map[key];
}
toArray() {
const array = [];
this.each(function (key, value) {
array.push(value);
});
return array;
}
}

38
src/core/structure/lru.js

@ -1,24 +1,21 @@
!(function () {
BI.LRU = function (limit) {
export class LRU {
constructor(limit) {
this.size = 0;
this.limit = limit;
this.head = this.tail = undefined;
this._keymap = {};
};
var p = BI.LRU.prototype;
}
p.put = function (key, value) {
var removed;
put(key, value) {
let removed;
if (this.size === this.limit) {
removed = this.shift();
}
var entry = this.get(key, true);
let entry = this.get(key, true);
if (!entry) {
entry = {
key: key
key: key,
};
this._keymap[key] = entry;
if (this.tail) {
@ -33,10 +30,10 @@
entry.value = value;
return removed;
};
}
p.shift = function () {
var entry = this.head;
shift() {
const entry = this.head;
if (entry) {
this.head = this.head.newer;
this.head.older = undefined;
@ -45,11 +42,10 @@
this.size--;
}
return entry;
};
}
p.get = function (key, returnEntry) {
var entry = this._keymap[key];
get(key, returnEntry) {
const entry = this._keymap[key];
if (entry === undefined) return;
if (entry === this.tail) {
return returnEntry
@ -78,9 +74,9 @@
return returnEntry
? entry
: entry.value;
};
}
p.has = function (key) {
has(key) {
return this._keymap[key] != null;
};
})();
}
}

291
src/core/structure/prefixIntervalTree.js

@ -1,32 +1,32 @@
// 线段树
(function () {
var parent = function (node) {
return Math.floor(node / 2);
};
var Int32Array = _global.Int32Array || function (size) {
var xs = [];
for (var i = size - 1; i >= 0; --i) {
xs[i] = 0;
}
return xs;
};
var ceilLog2 = function (x) {
var y = 1;
while (y < x) {
y *= 2;
}
return y;
};
BI.PrefixIntervalTree = function (xs) {
const parent = function (node) {
return Math.floor(node / 2);
};
const Int32Array = _global.Int32Array || function (size) {
const xs = [];
for (let i = size - 1; i >= 0; --i) {
xs[i] = 0;
}
return xs;
};
const ceilLog2 = function (x) {
let y = 1;
while (y < x) {
y *= 2;
}
return y;
};
export class PrefixIntervalTree {
constructor(xs) {
this._size = xs.length;
this._half = ceilLog2(this._size);
// _heap是一个_size两倍以上的堆
this._heap = new Int32Array(2 * this._half);
var i;
let i;
// 初始化 >= _size 的堆空间, 即叶子节点
for (i = 0; i < this._size; ++i) {
this._heap[this._half + i] = xs[i];
@ -35,146 +35,143 @@
for (i = this._half - 1; i > 0; --i) {
this._heap[i] = this._heap[2 * i] + this._heap[2 * i + 1];
}
};
BI.PrefixIntervalTree.prototype = {
constructor: BI.PrefixIntervalTree,
// 往_half之后的空间set值,需要更新其所有祖先节点的值
set: function (index, value) {
var node = this._half + index;
this._heap[node] = value;
node = parent(node);
for (; node !== 0; node = parent(node)) {
this._heap[node] =
this._heap[2 * node] + this._heap[2 * node + 1];
}
},
}
get: function (index) {
var node = this._half + index;
return this._heap[node];
},
static uniform(size, initialValue) {
const xs = [];
for (let i = size - 1; i >= 0; --i) {
xs[i] = initialValue;
}
getSize: function () {
return this._size;
},
/**
* get(0) + get(1) + ... + get(end - 1).
*/
sumUntil: function (end) {
if (end === 0) {
return 0;
}
return new PrefixIntervalTree(xs);
}
var node = this._half + end - 1;
var sum = this._heap[node];
for (; node !== 1; node = parent(node)) {
if (node % 2 === 1) {
sum += this._heap[node - 1];
}
}
static empty(size) {
return PrefixIntervalTree.uniform(size, 0);
}
return sum;
},
/**
* get(0) + get(1) + ... + get(inclusiveEnd).
*/
sumTo: function (inclusiveEnd) {
return this.sumUntil(inclusiveEnd + 1);
},
/**
* sum get(begin) + get(begin + 1) + ... + get(end - 1).
*/
sum: function (begin, end) {
return this.sumUntil(end) - this.sumUntil(begin);
},
/**
* Returns the smallest i such that 0 <= i <= size and sumUntil(i) <= t, or
* -1 if no such i exists.
*/
greatestLowerBound: function (t) {
if (t < 0) {
return -1;
}
set(index, value) {
let node = this._half + index;
this._heap[node] = value;
var node = 1;
if (this._heap[node] <= t) {
return this._size;
}
node = parent(node);
for (; node !== 0; node = parent(node)) {
this._heap[node] =
this._heap[2 * node] + this._heap[2 * node + 1];
}
}
get(index) {
const node = this._half + index;
return this._heap[node];
}
getSize() {
return this._size;
}
/**
* get(0) + get(1) + ... + get(end - 1).
*/
sumUntil(end) {
if (end === 0) {
return 0;
}
while (node < this._half) {
var leftSum = this._heap[2 * node];
if (t < leftSum) {
node = 2 * node;
} else {
node = 2 * node + 1;
t -= leftSum;
}
let node = this._half + end - 1;
let sum = this._heap[node];
for (; node !== 1; node = parent(node)) {
if (node % 2 === 1) {
sum += this._heap[node - 1];
}
}
return node - this._half;
},
return sum;
}
/**
* get(0) + get(1) + ... + get(inclusiveEnd).
*/
sumTo(inclusiveEnd) {
return this.sumUntil(inclusiveEnd + 1);
}
/**
* sum get(begin) + get(begin + 1) + ... + get(end - 1).
*/
sum(begin, end) {
return this.sumUntil(end) - this.sumUntil(begin);
}
/**
* Returns the smallest i such that 0 <= i <= size and sumUntil(i) <= t, or
* -1 if no such i exists.
*/
greatestLowerBound(t) {
if (t < 0) {
return -1;
}
/**
* Returns the smallest i such that 0 <= i <= size and sumUntil(i) < t, or
* -1 if no such i exists.
*/
greatestStrictLowerBound: function (t) {
if (t <= 0) {
return -1;
}
let node = 1;
if (this._heap[node] <= t) {
return this._size;
}
var node = 1;
if (this._heap[node] < t) {
return this._size;
while (node < this._half) {
const leftSum = this._heap[2 * node];
if (t < leftSum) {
node = 2 * node;
} else {
node = 2 * node + 1;
t -= leftSum;
}
}
while (node < this._half) {
var leftSum = this._heap[2 * node];
if (t <= leftSum) {
node = 2 * node;
} else {
node = 2 * node + 1;
t -= leftSum;
}
}
return node - this._half;
}
return node - this._half;
},
/**
* Returns the smallest i such that 0 <= i <= size and t <= sumUntil(i), or
* size + 1 if no such i exists.
*/
leastUpperBound: function (t) {
return this.greatestStrictLowerBound(t) + 1;
},
/**
* Returns the smallest i such that 0 <= i <= size and t < sumUntil(i), or
* size + 1 if no such i exists.
*/
leastStrictUpperBound: function (t) {
return this.greatestLowerBound(t) + 1;
/**
* Returns the smallest i such that 0 <= i <= size and sumUntil(i) < t, or
* -1 if no such i exists.
*/
greatestStrictLowerBound(t) {
if (t <= 0) {
return -1;
}
};
BI.PrefixIntervalTree.uniform = function (size, initialValue) {
var xs = [];
for (var i = size - 1; i >= 0; --i) {
xs[i] = initialValue;
let node = 1;
if (this._heap[node] < t) {
return this._size;
}
return new BI.PrefixIntervalTree(xs);
};
while (node < this._half) {
const leftSum = this._heap[2 * node];
if (t <= leftSum) {
node = 2 * node;
} else {
node = 2 * node + 1;
t -= leftSum;
}
}
return node - this._half;
}
/**
* Returns the smallest i such that 0 <= i <= size and t <= sumUntil(i), or
* size + 1 if no such i exists.
*/
leastUpperBound(t) {
return this.greatestStrictLowerBound(t) + 1;
}
/**
* Returns the smallest i such that 0 <= i <= size and t < sumUntil(i), or
* size + 1 if no such i exists.
*/
leastStrictUpperBound(t) {
return this.greatestLowerBound(t) + 1;
}
BI.PrefixIntervalTree.empty = function (size) {
return BI.PrefixIntervalTree.uniform(size, 0);
};
})();
}

143
src/core/structure/queue.js

@ -1,89 +1,86 @@
import {contains, remove} from "../2.base";
!(function () {
BI.Queue = function (capacity) {
export class Queue {
constructor(capacity) {
this.capacity = capacity;
this.array = [];
};
BI.Queue.prototype = {
constructor: BI.Queue,
contains: function (v) {
return BI.contains(this.array, v);
},
indexOf: function (v) {
return BI.contains(this.array, v);
},
getElementByIndex: function (index) {
return this.array[index];
},
push: function (v) {
this.array.push(v);
if (this.capacity && this.array.length > this.capacity) {
this.array.shift();
}
},
}
pop: function () {
this.array.pop();
},
contains(v) {
return contains(this.array, v);
}
indexOf(v) {
return contains(this.array, v);
}
getElementByIndex(index) {
return this.array[index];
}
shift: function () {
push(v) {
this.array.push(v);
if (this.capacity && this.array.length > this.capacity) {
this.array.shift();
},
}
}
unshift: function (v) {
this.array.unshift(v);
if (this.capacity && this.array.length > this.capacity) {
this.array.pop();
}
},
pop() {
this.array.pop();
}
shift() {
this.array.shift();
}
unshift(v) {
this.array.unshift(v);
if (this.capacity && this.array.length > this.capacity) {
this.array.pop();
}
}
remove: function (v) {
BI.remove(this.array, v);
},
remove(v) {
remove(this.array, v);
}
splice: function () {
this.array.splice.apply(this.array, arguments);
},
splice() {
this.array.splice.apply(this.array, arguments);
}
slice: function () {
this.array.slice.apply(this.array, arguments);
},
slice() {
this.array.slice.apply(this.array, arguments);
}
size: function () {
return this.array.length;
},
size() {
return this.array.length;
}
each: function (fn, scope) {
var scope = scope || window;
var fn = fn || null;
if (fn == null || typeof (fn) !== "function") {
return;
}
for (var i = 0; i < this.array.length; i++) {
var re = fn.call(scope, i, this.array[i], this.array);
if (re == false) {
break;
}
each(fn, scope) {
scope = scope || window;
fn = fn || null;
if (fn == null || typeof (fn) !== "function") {
return;
}
for (let i = 0; i < this.array.length; i++) {
const re = fn.call(scope, i, this.array[i], this.array);
if (re === false) {
break;
}
},
}
}
toArray: function () {
return this.array;
},
toArray() {
return this.array;
}
fromArray(array) {
array.each(v => this.push(v));
}
clear() {
this.array.length = 0;
}
}
fromArray: function (array) {
var self = this;
BI.each(array, function (i, v) {
self.push(v);
});
},
clear: function () {
this.array.length = 0;
}
};
})();

121
src/core/structure/sectionManager.js

@ -1,5 +1,7 @@
!(function () {
var Section = function (height, width, x, y) {
import {each, keys, map, size} from "../2.base";
class Section {
constructor(height, width, x, y) {
this.height = height;
this.width = width;
this.x = x;
@ -7,82 +9,79 @@
this._indexMap = {};
this._indices = [];
};
Section.prototype = {
constructor: Section,
addCellIndex: function (index) {
if (!this._indexMap[index]) {
this._indexMap[index] = true;
this._indices.push(index);
}
},
}
getCellIndices: function () {
return this._indices;
addCellIndex(index) {
if (!this._indexMap[index]) {
this._indexMap[index] = true;
this._indices.push(index);
}
};
}
getCellIndices() {
return this._indices;
}
}
var SECTION_SIZE = 100;
BI.SectionManager = function (sectionSize) {
this._sectionSize = sectionSize || SECTION_SIZE;
const SECTION_SIZE = 100;
export class SectionManager {
constructor(sectionSize = SECTION_SIZE) {
this._sectionSize = sectionSize;
this._cellMetadata = [];
this._sections = {};
};
BI.SectionManager.prototype = {
constructor: BI.SectionManager,
getCellIndices: function (height, width, x, y) {
var indices = {};
}
BI.each(this.getSections(height, width, x, y), function (i, section) {
BI.each(section.getCellIndices(), function (j, index) {
indices[index] = index;
});
});
getCellIndices(height, width, x, y) {
const indices = {};
return BI.map(BI.keys(indices), function (i, index) {
return indices[index];
each(this.getSections(height, width, x, y), function (i, section) {
each(section.getCellIndices(), function (j, index) {
indices[index] = index;
});
},
});
getCellMetadata: function (index) {
return this._cellMetadata[index];
},
return map(keys(indices), function (i, index) {
return indices[index];
});
}
getSections: function (height, width, x, y) {
var sectionXStart = Math.floor(x / this._sectionSize);
var sectionXStop = Math.floor((x + width - 1) / this._sectionSize);
var sectionYStart = Math.floor(y / this._sectionSize);
var sectionYStop = Math.floor((y + height - 1) / this._sectionSize);
getCellMetadata(index) {
return this._cellMetadata[index];
}
var sections = [];
getSections(height, width, x, y) {
const sectionXStart = Math.floor(x / this._sectionSize);
const sectionXStop = Math.floor((x + width - 1) / this._sectionSize);
const sectionYStart = Math.floor(y / this._sectionSize);
const sectionYStop = Math.floor((y + height - 1) / this._sectionSize);
for (var sectionX = sectionXStart; sectionX <= sectionXStop; sectionX++) {
for (var sectionY = sectionYStart; sectionY <= sectionYStop; sectionY++) {
var key = sectionX + "." + sectionY;
const sections = [];
if (!this._sections[key]) {
this._sections[key] = new Section(this._sectionSize, this._sectionSize, sectionX * this._sectionSize, sectionY * this._sectionSize);
}
for (let sectionX = sectionXStart; sectionX <= sectionXStop; sectionX++) {
for (let sectionY = sectionYStart; sectionY <= sectionYStop; sectionY++) {
const key = sectionX + "." + sectionY;
sections.push(this._sections[key]);
if (!this._sections[key]) {
this._sections[key] = new Section(this._sectionSize, this._sectionSize, sectionX * this._sectionSize, sectionY * this._sectionSize);
}
sections.push(this._sections[key]);
}
}
return sections;
},
return sections;
}
getTotalSectionCount: function () {
return BI.size(this._sections);
},
getTotalSectionCount() {
return size(this._sections);
}
registerCell: function (cellMetadatum, index) {
this._cellMetadata[index] = cellMetadatum;
registerCell(cellMetadatum, index) {
this._cellMetadata[index] = cellMetadatum;
BI.each(this.getSections(cellMetadatum.height, cellMetadatum.width, cellMetadatum.x, cellMetadatum.y), function (i, section) {
section.addCellIndex(index);
});
}
};
})();
each(this.getSections(cellMetadatum.height, cellMetadatum.width, cellMetadatum.x, cellMetadatum.y), function (i, section) {
section.addCellIndex(index);
});
}
}

934
src/core/structure/tree.js

@ -1,517 +1,521 @@
(function () {
BI.Tree = function () {
this.root = new BI.Node(BI.UUID());
};
BI.Tree.prototype = {
constructor: BI.Tree,
addNode: function (node, newNode, index) {
if (BI.isNull(newNode)) {
this.root.addChild(node, index);
} else if (BI.isNull(node)) {
this.root.addChild(newNode, index);
} else {
node.addChild(newNode, index);
}
},
isRoot: function (node) {
return node === this.root;
},
getRoot: function () {
return this.root;
},
clear: function () {
this.root.clear();
},
initTree: function (nodes) {
var self = this;
this.clear();
var queue = [];
BI.each(nodes, function (i, node) {
var n = new BI.Node(node);
n.set("data", node);
self.addNode(n);
queue.push(n);
});
while (!BI.isEmpty(queue)) {
var parent = queue.shift();
var node = parent.get("data");
BI.each(node.children, function (i, child) {
var n = new BI.Node(child);
n.set("data", child);
queue.push(n);
self.addNode(parent, n);
});
}
},
import {
isObject,
UUID,
extend,
isEmpty,
isArray,
first,
last,
findIndex,
isUndefined,
isNull,
each,
deepClone,
isEqual, some, every, clone
} from "../2.base";
export class Node {
constructor(id) {
if (isObject(id)) {
extend(this, id);
} else {
this.id = id;
}
this.clear();
}
_toJSON: function (node) {
var self = this;
var children = [];
BI.each(node.getChildren(), function (i, child) {
children.push(self._toJSON(child));
});
return BI.extend({
id: node.id
}, BI.deepClone(node.get("data")), (children.length > 0 ? {
children: children
} : {}));
},
toJSON: function (node) {
var self = this, result = [];
BI.each((node || this.root).getChildren(), function (i, child) {
result.push(self._toJSON(child));
});
return result;
},
_toJSONWithNode: function (node) {
var self = this;
var children = [];
BI.each(node.getChildren(), function (i, child) {
children.push(self._toJSONWithNode(child));
});
return BI.extend({
id: node.id
}, BI.deepClone(node.get("data")), {
node: node
}, (children.length > 0 ? {
children: children
} : {}));
},
toJSONWithNode: function (node) {
var self = this, result = [];
BI.each((node || this.root).getChildren(), function (i, child) {
result.push(self._toJSONWithNode(child));
set(key, value) {
if (isObject(key)) {
extend(this, key);
return;
}
this[key] = value;
}
get(key) {
return this[key];
}
isLeaf() {
return isEmpty(this.children);
}
getChildren() {
return this.children;
}
getChildrenLength() {
return this.children.length;
}
getFirstChild() {
return first(this.children);
}
getLastChild() {
return last(this.children);
}
setLeft(left) {
this.left = left;
}
getLeft() {
return this.left;
}
setRight(right) {
this.right = right;
}
getRight() {
return this.right;
}
setParent(parent) {
this.parent = parent;
}
getParent() {
return this.parent;
}
getChild(index) {
return this.children[index];
}
getChildIndex(id) {
return findIndex(this.children, function (i, ch) {
return ch.get("id") === id;
});
}
removeChild(id) {
this.removeChildByIndex(this.getChildIndex(id));
}
removeChildByIndex(index) {
const before = this.getChild(index - 1);
const behind = this.getChild(index + 1);
if (before != null) {
before.setRight(behind || null);
}
if (behind != null) {
behind.setLeft(before || null);
}
this.children.splice(index, 1);
}
removeAllChilds() {
this.children = [];
}
addChild(child, index) {
let cur = null;
if (isUndefined(index)) {
cur = this.children.length - 1;
} else {
cur = index - 1;
}
child.setParent(this);
if (cur >= 0) {
this.getChild(cur) && this.getChild(cur).setRight(child);
child.setLeft(this.getChild(cur));
}
if (isUndefined(index)) {
this.children.push(child);
} else {
this.children.splice(index, 0, child);
}
}
equals(obj) {
return this === obj || this.id === obj.id;
}
clear() {
this.parent = null;
this.left = null;
this.right = null;
this.children = [];
}
}
export class Tree {
constructor() {
this.root = new Node(UUID());
}
addNode(node, newNode, index) {
if (isNull(newNode)) {
this.root.addChild(node, index);
} else if (isNull(node)) {
this.root.addChild(newNode, index);
} else {
node.addChild(newNode, index);
}
}
isRoot(node) {
return node === this.root;
}
getRoot() {
return this.root;
}
clear() {
this.root.clear();
}
initTree(nodes) {
this.clear();
const queue = [];
each(nodes, (i, node) => {
const n = new Node(node);
n.set("data", node);
this.addNode(n);
queue.push(n);
});
while (!isEmpty(queue)) {
const parent = queue.shift();
const node = parent.get("data");
each(node.children, (i, child) => {
const n = new Node(child);
n.set("data", child);
queue.push(n);
this.addNode(parent, n);
});
return result;
},
}
}
_toJSON(node) {
const children = [];
each(node.getChildren(), (i, child) => {
children.push(this._toJSON(child));
});
return extend({
id: node.id,
}, deepClone(node.get("data")), (children.length > 0 ? {
children: children,
} : {}));
}
toJSON(node) {
const result = [];
each((node || this.root).getChildren(), (i, child) => {
result.push(this._toJSON(child));
});
return result;
}
_toJSONWithNode(node) {
const children = [];
each(node.getChildren(), (i, child) => {
children.push(this._toJSONWithNode(child));
});
return extend({
id: node.id,
}, deepClone(node.get("data")), {
node: node,
}, (children.length > 0 ? {
children: children,
} : {}));
}
toJSONWithNode(node) {
const result = [];
each((node || this.root).getChildren(), (i, child) => {
result.push(this._toJSONWithNode(child));
});
return result;
}
search(root, target, param) {
if (!(root instanceof Node)) {
return this.search(this.root, root, target);
}
let next = null;
search: function (root, target, param) {
if (!(root instanceof BI.Node)) {
return arguments.callee.apply(this, [this.root, root, target]);
if (isNull(target)) {
return null;
}
if (isEqual(root[param || "id"], target)) {
return root;
}
some(root.getChildren(), (i, child) => {
next = this.search(child, target, param);
if (null !== next) {
return true;
}
var self = this, next = null;
if (BI.isNull(target)) {
return null;
});
return next;
}
_traverse(node, callback) {
let queue = [];
queue.push(node);
while (!isEmpty(queue)) {
const temp = queue.shift();
const b = callback && callback(temp);
if (b === false) {
break;
}
if (BI.isEqual(root[param || "id"], target)) {
return root;
if (b === true) {
continue;
}
BI.any(root.getChildren(), function (i, child) {
next = self.search(child, target, param);
if (null !== next) {
return true;
}
});
return next;
},
_traverse: function (node, callback) {
var queue = [];
queue.push(node);
while (!BI.isEmpty(queue)) {
var temp = queue.shift();
var b = callback && callback(temp);
if (b === false) {
break;
}
if (b === true) {
continue;
}
if (temp != null) {
queue = queue.concat(temp.getChildren());
}
if (temp != null) {
queue = queue.concat(temp.getChildren());
}
},
traverse: function (callback) {
this._traverse(this.root, callback);
},
_recursion: function (node, route, callback) {
var self = this;
return BI.every(node.getChildren(), function (i, child) {
var next = BI.clone(route);
next.push(child.id);
var b = callback && callback(child, next);
if (b === false) {
return false;
}
if (b === true) {
return true;
}
return self._recursion(child, next, callback);
});
},
recursion: function (callback) {
this._recursion(this.root, [], callback);
},
inOrderTraverse: function (callback) {
this._inOrderTraverse(this.root, callback);
},
// 中序遍历(递归)
_inOrderTraverse: function (node, callback) {
if (node != null) {
this._inOrderTraverse(node.getLeft());
callback && callback(node);
this._inOrderTraverse(node.getRight());
}
}
traverse(callback) {
this._traverse(this.root, callback);
}
_recursion(node, route, callback) {
return every(node.getChildren(), (i, child) => {
const next = clone(route);
next.push(child.id);
const b = callback && callback(child, next);
if (b === false) {
return false;
}
},
// 中序遍历(非递归)
nrInOrderTraverse: function (callback) {
var stack = [];
var node = this.root;
while (node != null || !BI.isEmpty(stack)) {
while (node != null) {
stack.push(node);
node = node.getLeft();
}
node = stack.pop();
callback && callback(node);
node = node.getRight();
if (b === true) {
return true;
}
},
return this._recursion(child, next, callback);
});
}
recursion(callback) {
this._recursion(this.root, [], callback);
}
inOrderTraverse(callback) {
this._inOrderTraverse(this.root, callback);
}
// 中序遍历(递归)
_inOrderTraverse(node, callback) {
if (node != null) {
this._inOrderTraverse(node.getLeft());
callback && callback(node);
this._inOrderTraverse(node.getRight());
}
}
preOrderTraverse: function (callback) {
this._preOrderTraverse(this.root, callback);
},
// 中序遍历(非递归)
nrInOrderTraverse(callback) {
// 先序遍历(递归)
_preOrderTraverse: function (node, callback) {
if (node != null) {
callback && callback(node);
this._preOrderTraverse(node.getLeft());
this._preOrderTraverse(node.getRight());
const stack = [];
let node = this.root;
while (node != null || !isEmpty(stack)) {
while (node != null) {
stack.push(node);
node = node.getLeft();
}
},
// 先序遍历(非递归)
nrPreOrderTraverse: function (callback) {
var stack = [];
var node = this.root;
node = stack.pop();
callback && callback(node);
node = node.getRight();
}
}
preOrderTraverse(callback) {
this._preOrderTraverse(this.root, callback);
}
// 先序遍历(递归)
_preOrderTraverse(node, callback) {
if (node != null) {
callback && callback(node);
this._preOrderTraverse(node.getLeft());
this._preOrderTraverse(node.getRight());
}
}
while (node != null || !BI.isEmpty(stack)) {
// 先序遍历(非递归)
nrPreOrderTraverse(callback) {
while (node != null) {
callback && callback(node);
stack.push(node);
node = node.getLeft();
}
node = stack.pop();
node = node.getRight();
}
},
const stack = [];
let node = this.root;
postOrderTraverse: function (callback) {
this._postOrderTraverse(this.root, callback);
},
while (node != null || !isEmpty(stack)) {
// 后序遍历(递归)
_postOrderTraverse: function (node, callback) {
if (node != null) {
this._postOrderTraverse(node.getLeft());
this._postOrderTraverse(node.getRight());
while (node != null) {
callback && callback(node);
stack.push(node);
node = node.getLeft();
}
},
// 后续遍历(非递归)
nrPostOrderTraverse: function (callback) {
var stack = [];
var node = this.root;
var preNode = null;// 表示最近一次访问的节点
while (node != null || !BI.isEmpty(stack)) {
while (node != null) {
stack.push(node);
node = node.getLeft();
}
node = BI.last(stack);
if (node.getRight() == null || node.getRight() == preNode) {
callback && callback(node);
node = stack.pop();
preNode = node;
node = null;
} else {
node = node.getRight();
}
}
node = stack.pop();
node = node.getRight();
}
};
BI.Node = function (id) {
if (BI.isObject(id)) {
BI.extend(this, id);
} else {
this.id = id;
}
postOrderTraverse(callback) {
this._postOrderTraverse(this.root, callback);
}
// 后序遍历(递归)
_postOrderTraverse(node, callback) {
if (node != null) {
this._postOrderTraverse(node.getLeft());
this._postOrderTraverse(node.getRight());
callback && callback(node);
}
this.clear.apply(this, arguments);
};
BI.Node.prototype = {
constructor: BI.Node,
set: function (key, value) {
if (BI.isObject(key)) {
BI.extend(this, key);
return;
}
this[key] = value;
},
get: function (key) {
return this[key];
},
isLeaf: function () {
return BI.isEmpty(this.children);
},
getChildren: function () {
return this.children;
},
getChildrenLength: function () {
return this.children.length;
},
getFirstChild: function () {
return BI.first(this.children);
},
getLastChild: function () {
return BI.last(this.children);
},
}
setLeft: function (left) {
this.left = left;
},
// 后续遍历(非递归)
nrPostOrderTraverse(callback) {
getLeft: function () {
return this.left;
},
const stack = [];
let node = this.root;
let preNode = null;// 表示最近一次访问的节点
setRight: function (right) {
this.right = right;
},
while (node != null || !isEmpty(stack)) {
getRight: function () {
return this.right;
},
setParent: function (parent) {
this.parent = parent;
},
getParent: function () {
return this.parent;
},
getChild: function (index) {
return this.children[index];
},
getChildIndex: function (id) {
return BI.findIndex(this.children, function (i, ch) {
return ch.get("id") === id;
});
},
removeChild: function (id) {
this.removeChildByIndex(this.getChildIndex(id));
},
removeChildByIndex: function (index) {
var before = this.getChild(index - 1);
var behind = this.getChild(index + 1);
if (before != null) {
before.setRight(behind || null);
}
if (behind != null) {
behind.setLeft(before || null);
while (node != null) {
stack.push(node);
node = node.getLeft();
}
this.children.splice(index, 1);
},
removeAllChilds: function () {
this.children = [];
},
node = last(stack);
addChild: function (child, index) {
var cur = null;
if (BI.isUndefined(index)) {
cur = this.children.length - 1;
if (node.getRight() == null || node.getRight() === preNode) {
callback && callback(node);
node = stack.pop();
preNode = node;
node = null;
} else {
cur = index - 1;
node = node.getRight();
}
child.setParent(this);
if (cur >= 0) {
this.getChild(cur) && this.getChild(cur).setRight(child);
child.setLeft(this.getChild(cur));
}
}
static transformToArrayFormat(nodes, pId, childKey) {
if (!nodes) return [];
let r = [];
childKey = childKey || "children";
if (isArray(nodes)) {
for (let i = 0, l = nodes.length; i < l; i++) {
const node = clone(nodes[i]);
node.pId = node.pId == null ? pId : node.pId;
delete node.children;
r.push(node);
if (nodes[i][childKey]) {
r = r.concat(Tree.transformToArrayFormat(nodes[i][childKey], node.id));
}
}
if (BI.isUndefined(index)) {
this.children.push(child);
} else {
this.children.splice(index, 0, child);
} else {
const newNodes = clone(nodes);
newNodes.pId = newNodes.pId == null ? pId : newNodes.pId;
delete newNodes.children;
r.push(newNodes);
if (nodes[childKey]) {
r = r.concat(Tree.transformToArrayFormat(nodes[childKey], newNodes.id));
}
},
equals: function (obj) {
return this === obj || this.id === obj.id;
},
}
return r;
}
clear: function () {
this.parent = null;
this.left = null;
this.right = null;
this.children = [];
static arrayFormat(nodes, pId) {
if (!nodes) {
return [];
}
};
BI.extend(BI.Tree, {
transformToArrayFormat: function (nodes, pId, childKey) {
if (!nodes) return [];
var r = [];
childKey = childKey || "children";
if (BI.isArray(nodes)) {
for (var i = 0, l = nodes.length; i < l; i++) {
var node = BI.clone(nodes[i]);
node.pId = node.pId == null ? pId : node.pId;
delete node.children;
r.push(node);
if (nodes[i][childKey]) {
r = r.concat(BI.Tree.transformToArrayFormat(nodes[i][childKey], node.id));
}
}
} else {
var newNodes = BI.clone(nodes);
newNodes.pId = newNodes.pId == null ? pId : newNodes.pId;
delete newNodes.children;
r.push(newNodes);
if (nodes[childKey]) {
r = r.concat(BI.Tree.transformToArrayFormat(nodes[childKey], newNodes.id));
let r = [];
if (isArray(nodes)) {
for (let i = 0, l = nodes.length; i < l; i++) {
const node = nodes[i];
node.pId = node.pId == null ? pId : node.pId;
r.push(node);
if (nodes[i]["children"]) {
r = r.concat(Tree.arrayFormat(nodes[i]["children"], node.id));
}
}
return r;
},
arrayFormat: function (nodes, pId) {
if (!nodes) {
return [];
}
var r = [];
if (BI.isArray(nodes)) {
for (var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i];
node.pId = node.pId == null ? pId : node.pId;
r.push(node);
if (nodes[i]["children"]) {
r = r.concat(BI.Tree.arrayFormat(nodes[i]["children"], node.id));
}
}
} else {
var newNodes = nodes;
newNodes.pId = newNodes.pId == null ? pId : newNodes.pId;
r.push(newNodes);
if (nodes["children"]) {
r = r.concat(BI.Tree.arrayFormat(nodes["children"], newNodes.id));
}
} else {
const newNodes = nodes;
newNodes.pId = newNodes.pId == null ? pId : newNodes.pId;
r.push(newNodes);
if (nodes["children"]) {
r = r.concat(Tree.arrayFormat(nodes["children"], newNodes.id));
}
return r;
},
}
return r;
}
transformToTreeFormat: function (sNodes) {
var i, l;
if (!sNodes) {
return [];
}
static transformToTreeFormat(sNodes) {
let i, l;
if (!sNodes) {
return [];
}
if (BI.isArray(sNodes)) {
var r = [];
var tmpMap = {};
for (i = 0, l = sNodes.length; i < l; i++) {
if (BI.isNull(sNodes[i].id)) {
return sNodes;
}
tmpMap[sNodes[i].id] = BI.clone(sNodes[i]);
if (isArray(sNodes)) {
const r = [];
const tmpMap = {};
for (i = 0, l = sNodes.length; i < l; i++) {
if (isNull(sNodes[i].id)) {
return sNodes;
}
for (i = 0, l = sNodes.length; i < l; i++) {
if (tmpMap[sNodes[i].pId] && sNodes[i].id !== sNodes[i].pId) {
if (!tmpMap[sNodes[i].pId].children) {
tmpMap[sNodes[i].pId].children = [];
}
tmpMap[sNodes[i].pId].children.push(tmpMap[sNodes[i].id]);
} else {
r.push(tmpMap[sNodes[i].id]);
tmpMap[sNodes[i].id] = clone(sNodes[i]);
}
for (i = 0, l = sNodes.length; i < l; i++) {
if (tmpMap[sNodes[i].pId] && sNodes[i].id !== sNodes[i].pId) {
if (!tmpMap[sNodes[i].pId].children) {
tmpMap[sNodes[i].pId].children = [];
}
delete tmpMap[sNodes[i].id].pId;
tmpMap[sNodes[i].pId].children.push(tmpMap[sNodes[i].id]);
} else {
r.push(tmpMap[sNodes[i].id]);
}
return r;
delete tmpMap[sNodes[i].id].pId;
}
return [sNodes];
return r;
}
return [sNodes];
},
}
treeFormat: function (sNodes) {
var i, l;
if (!sNodes) {
return [];
}
static treeFormat(sNodes) {
let i, l;
if (!sNodes) {
return [];
}
if (BI.isArray(sNodes)) {
var r = [];
var tmpMap = {};
for (i = 0, l = sNodes.length; i < l; i++) {
if (BI.isNull(sNodes[i].id)) {
return sNodes;
}
tmpMap[sNodes[i].id] = sNodes[i];
if (isArray(sNodes)) {
const r = [];
const tmpMap = {};
for (i = 0, l = sNodes.length; i < l; i++) {
if (isNull(sNodes[i].id)) {
return sNodes;
}
for (i = 0, l = sNodes.length; i < l; i++) {
if (tmpMap[sNodes[i].pId] && sNodes[i].id !== sNodes[i].pId) {
if (!tmpMap[sNodes[i].pId].children) {
tmpMap[sNodes[i].pId].children = [];
}
tmpMap[sNodes[i].pId].children.push(tmpMap[sNodes[i].id]);
} else {
r.push(tmpMap[sNodes[i].id]);
tmpMap[sNodes[i].id] = sNodes[i];
}
for (i = 0, l = sNodes.length; i < l; i++) {
if (tmpMap[sNodes[i].pId] && sNodes[i].id !== sNodes[i].pId) {
if (!tmpMap[sNodes[i].pId].children) {
tmpMap[sNodes[i].pId].children = [];
}
tmpMap[sNodes[i].pId].children.push(tmpMap[sNodes[i].id]);
} else {
r.push(tmpMap[sNodes[i].id]);
}
return r;
}
return [sNodes];
return r;
}
return [sNodes];
},
}
traversal: function (array, callback, pNode) {
if (BI.isNull(array)) {
return;
}
var self = this;
BI.some(array, function (i, item) {
if (callback(i, item, pNode) === false) {
return true;
}
self.traversal(item.children, callback, item);
});
static traversal(array, callback, pNode) {
if (isNull(array)) {
return;
}
});
})();
some(array, (i, item) => {
if (callback(i, item, pNode) === false) {
return true;
}
this.traversal(item.children, callback, item);
});
}
}

61
src/core/structure/vector.js

@ -1,27 +1,29 @@
// 向量操作
BI.Vector = function (x, y) {
this.x = x;
this.y = y;
};
BI.Vector.prototype = {
constructor: BI.Vector,
cross: function (v) {
export class Vector {
constructor(x, y) {
this.x = x;
this.y = y;
}
cross(v) {
return (this.x * v.y - this.y * v.x);
},
length: function (v) {
}
length(v) {
return (Math.sqrt(this.x * v.x + this.y * v.y));
}
};
BI.Region = function (x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
};
BI.Region.prototype = {
constructor: BI.Region,
}
export class Region {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
// 判断两个区域是否相交,若相交,则要么顶点互相包含,要么矩形边界(或对角线)相交
isIntersects: function (obj) {
isIntersects(obj) {
if (this.isPointInside(obj.x, obj.y) ||
this.isPointInside(obj.x + obj.w, obj.y) ||
this.isPointInside(obj.x, obj.y + obj.h) ||
@ -34,17 +36,18 @@ BI.Region.prototype = {
return true;
} else if (obj.x != null && obj.y != null)// 判断矩形对角线相交 |v1 X v2||v1 X v3| < 0
{
var vector1 = new BI.Vector(this.w, this.h);// 矩形对角线向量
var vector2 = new BI.Vector(obj.x - this.x, obj.y - this.y);
var vector3 = new BI.Vector(vector2.x + obj.w, vector2.y + obj.h);
const vector1 = new Vector(this.w, this.h);// 矩形对角线向量
const vector2 = new Vector(obj.x - this.x, obj.y - this.y);
const vector3 = new Vector(vector2.x + obj.w, vector2.y + obj.h);
if ((vector1.cross(vector2) * vector1.cross(vector3)) < 0) {
return true;
}
}
return false;
},
}
// 判断一个点是否在这个区域内部
isPointInside: function (x, y) {
isPointInside(x, y) {
if (this.x == null || this.y == null) {
return false;
}
@ -52,12 +55,14 @@ BI.Region.prototype = {
return true;
}
return false;
},
}
// 返回区域的重心,因为是矩形所以返回中点
getPosition: function () {
var pos = [];
getPosition() {
const pos = [];
pos.push(this.x + this.w / 2);
pos.push(this.y + this.h / 2);
return pos;
}
};
}

Loading…
Cancel
Save