@vitrosoftware/common-ui-ts 1.1.122 → 1.1.124
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/std/controls/checkbox/checkbox.css +4 -0
- package/css/std/controls/checkbox/img/checkbox-indeterminate.svg +4 -0
- package/css/std/controls/date-picker/date-picker.css +1 -25
- package/css/std/controls/dxf-viewer/annotation.css +85 -0
- package/css/std/controls/dxf-viewer/common.css +24 -0
- package/css/std/controls/dxf-viewer/dxf-viewer-index.css +14081 -0
- package/css/std/controls/dxf-viewer/dxf-viewer.css +194 -0
- package/css/std/controls/dxf-viewer/img/cancel-dark-grey.svg +5 -0
- package/css/std/controls/dxf-viewer/img/collapse-bottom.svg +5 -0
- package/css/std/controls/dxf-viewer/img/collapse-up-blue.svg +5 -0
- package/css/std/controls/dxf-viewer/img/delete-active.svg +11 -0
- package/css/std/controls/dxf-viewer/img/delete.svg +11 -0
- package/css/std/controls/dxf-viewer/img/draw-annotation.svg +3 -0
- package/css/std/controls/dxf-viewer/img/invisible-eye.svg +4 -0
- package/css/std/controls/dxf-viewer/img/show-annotation.svg +3 -0
- package/css/std/controls/dxf-viewer/img/sidebar-layers-toggle.svg +6 -0
- package/css/std/controls/dxf-viewer/img/sidebar-notes-toggle.svg +5 -0
- package/css/std/controls/dxf-viewer/img/sidebar-resizer.svg +6 -0
- package/css/std/controls/dxf-viewer/img/sidebar-toggle.svg +7 -0
- package/css/std/controls/dxf-viewer/img/visible-eye.svg +4 -0
- package/css/std/controls/dxf-viewer/img/zoom-in.svg +6 -0
- package/css/std/controls/dxf-viewer/img/zoom-out.svg +5 -0
- package/css/std/controls/dxf-viewer/layer-list.css +104 -0
- package/css/std/controls/dxf-viewer/panel.css +34 -0
- package/css/std/controls/dxf-viewer/prop-inspector.css +102 -0
- package/css/std/controls/dxf-viewer/select.css +111 -0
- package/css/std/controls/dxf-viewer/sidebar.css +190 -0
- package/css/std/controls/dxf-viewer/thumbnail-list.css +65 -0
- package/css/std/controls/dxf-viewer/toolbar.css +117 -0
- package/css/std/controls/dxf-viewer/treeview.css +3 -0
- package/css/std/controls/dxf-viewer/treeview.panel.css +108 -0
- package/css/std/controls/error-message/error-message.css +22 -0
- package/css/std/controls/image-picker/image-picker.css +0 -26
- package/css/std/controls/input/input.css +1 -24
- package/css/std/controls/issue-tile/issue-tile-header.css +1 -0
- package/css/std/controls/login/ntlm-authentication-form.css +9 -12
- package/css/std/controls/lookup-picker/lookup-picker-value-list.css +38 -2
- package/css/std/controls/lookup-picker/lookup-picker.css +1 -25
- package/css/std/controls/table-view/treegrid-context-menu.css +44 -18
- package/css/std/controls/table-view/treegrid-message.css +4 -4
- package/css/std/controls/time-picker/time-picker.css +1 -25
- package/dist/index.css +81 -143
- package/dist/index.js +15137 -489
- package/dist/index.js.map +1 -1
- package/dist/src/controls/Checkbox/Checkbox.d.ts +1 -0
- package/dist/src/controls/DxfViewer/DxfViewer.d.ts +6 -0
- package/dist/src/controls/DxfViewer/DxfViewerContext.d.ts +31 -0
- package/dist/src/controls/DxfViewer/Layer.d.ts +9 -0
- package/dist/src/controls/DxfViewer/LayerList.d.ts +11 -0
- package/dist/src/controls/DxfViewer/Thumbnail.d.ts +7 -0
- package/dist/src/controls/DxfViewer/ThumbnailList.d.ts +6 -0
- package/dist/src/controls/DxfViewer/Viewer.d.ts +6 -0
- package/dist/src/controls/ErrorMessage/ErrorMessage.d.ts +6 -0
- package/dist/src/controls/Login/FormRef.d.ts +3 -0
- package/dist/src/controls/Login/LoginConstants.d.ts +2 -1
- package/dist/src/controls/Login/LoginFormRef.d.ts +2 -2
- package/dist/src/controls/Login/NTLMAuthenticationForm.d.ts +5 -2
- package/dist/src/controls/LookupPicker/LookupPicker.d.ts +2 -0
- package/dist/src/controls/LookupPicker/ValueList.d.ts +2 -0
- package/dist/src/controls/TableView/TableViewConstants.d.ts +11 -0
- package/dist/src/controls/TableView/TreeGridTableViewContextImpl.d.ts +1 -0
- package/dist/src/controls/TreeView/TreeView.d.ts +4 -0
- package/dist/src/controls/TreeView/TreeViewConfig.d.ts +3 -0
- package/dist/src/controls/TreeView/TreeViewConstants.d.ts +2 -1
- package/dist/src/index.d.ts +7 -1
- package/lib/dxf-viewer/BatchingKey.js +91 -0
- package/lib/dxf-viewer/DxfFetcher.js +39 -0
- package/lib/dxf-viewer/DxfScene.js +2695 -0
- package/lib/dxf-viewer/DxfViewer.js +1056 -0
- package/lib/dxf-viewer/DxfWorker.js +229 -0
- package/lib/dxf-viewer/DynamicBuffer.js +100 -0
- package/lib/dxf-viewer/HatchCalculator.js +345 -0
- package/lib/dxf-viewer/LinearDimension.js +323 -0
- package/lib/dxf-viewer/MTextFormatParser.js +211 -0
- package/lib/dxf-viewer/MaterialKey.js +37 -0
- package/lib/dxf-viewer/OrbitControls.js +1253 -0
- package/lib/dxf-viewer/Pattern.js +94 -0
- package/lib/dxf-viewer/RBTree.js +471 -0
- package/lib/dxf-viewer/TextRenderer.js +1038 -0
- package/lib/dxf-viewer/index.js +42 -0
- package/lib/dxf-viewer/math/Matrix2.js +77 -0
- package/lib/dxf-viewer/math/utils.js +59 -0
- package/lib/dxf-viewer/parser/AutoCadColorIndex.js +265 -0
- package/lib/dxf-viewer/parser/DimStyleCodes.js +33 -0
- package/lib/dxf-viewer/parser/DxfArrayScanner.js +143 -0
- package/lib/dxf-viewer/parser/DxfParser.js +980 -0
- package/lib/dxf-viewer/parser/ExtendedDataParse-My.js +91 -0
- package/lib/dxf-viewer/parser/ExtendedDataParser.js +123 -0
- package/lib/dxf-viewer/parser/ParseHelpers.js +142 -0
- package/lib/dxf-viewer/parser/entities/3dface.js +83 -0
- package/lib/dxf-viewer/parser/entities/arc.js +38 -0
- package/lib/dxf-viewer/parser/entities/attdef.js +89 -0
- package/lib/dxf-viewer/parser/entities/attrib.js +34 -0
- package/lib/dxf-viewer/parser/entities/attribute.js +109 -0
- package/lib/dxf-viewer/parser/entities/circle.js +43 -0
- package/lib/dxf-viewer/parser/entities/dimension.js +72 -0
- package/lib/dxf-viewer/parser/entities/ellipse.js +46 -0
- package/lib/dxf-viewer/parser/entities/hatch.js +343 -0
- package/lib/dxf-viewer/parser/entities/insert.js +62 -0
- package/lib/dxf-viewer/parser/entities/leader.js +84 -0
- package/lib/dxf-viewer/parser/entities/line.js +34 -0
- package/lib/dxf-viewer/parser/entities/lwpolyline.js +100 -0
- package/lib/dxf-viewer/parser/entities/mtext.js +54 -0
- package/lib/dxf-viewer/parser/entities/point.js +35 -0
- package/lib/dxf-viewer/parser/entities/polyline.js +92 -0
- package/lib/dxf-viewer/parser/entities/solid.js +40 -0
- package/lib/dxf-viewer/parser/entities/spline.js +70 -0
- package/lib/dxf-viewer/parser/entities/text.js +47 -0
- package/lib/dxf-viewer/parser/entities/vertex.js +62 -0
- package/lib/dxf-viewer/parser/entities/viewport.js +56 -0
- package/lib/dxf-viewer/parser/objects/dictionary.js +29 -0
- package/lib/dxf-viewer/parser/objects/layout.js +35 -0
- package/lib/dxf-viewer/parser/objects/xrecord.js +29 -0
- package/lib/opentype/opentype.module.js +14571 -0
- package/lib/three/CSS2DRenderer.js +235 -0
- package/lib/three/three.module.js +49912 -0
- package/package.json +12 -10
- package/src/controls/BimViewer/js/bim-viewer.js +2 -2
- package/src/controls/DxfViewer/js/dxf-viewer.js +3580 -0
- package/src/controls/PdfViewer/js/pdf-viewer.js +1 -1
- package/css/std/controls/input/img/error-message.svg +0 -6
- package/css/std/controls/lookup-picker/img/error-message.svg +0 -6
- package/css/std/controls/time-picker/img/error-message.svg +0 -6
- /package/css/std/controls/{date-picker → error-message}/img/error-message.svg +0 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Vector2 } from "/resource/dxfViewer/js/three/three.module.js"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef PatternLineDef
|
|
5
|
+
* @property {number} angle Line angle in radians.
|
|
6
|
+
* @property {?Vector2} base Base point for scaling, rotation and anchoring. [0,0] if not specified.
|
|
7
|
+
* @property {Vector2} offset Offset for line instantiation.
|
|
8
|
+
* @property {?number[]} dashes Dash lengths. Solid line if not specified. Negative numbers for
|
|
9
|
+
* spaces, positive for dashes, zero for dots.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export class Pattern {
|
|
13
|
+
/**
|
|
14
|
+
* @param {PatternLineDef[]} lines
|
|
15
|
+
*/
|
|
16
|
+
constructor(lines, name = null) {
|
|
17
|
+
this.lines = lines
|
|
18
|
+
this.name = name
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static ParsePatFile(content) {
|
|
22
|
+
const lines = content.split(/\r?\n/)
|
|
23
|
+
if (lines.length < 2) {
|
|
24
|
+
throw new Error("Invalid .pat file content")
|
|
25
|
+
}
|
|
26
|
+
let name = null
|
|
27
|
+
const lineDefs = []
|
|
28
|
+
for (let line of lines) {
|
|
29
|
+
line = line.trim()
|
|
30
|
+
if (line == "") {
|
|
31
|
+
continue
|
|
32
|
+
}
|
|
33
|
+
if (line.startsWith(";")) {
|
|
34
|
+
continue
|
|
35
|
+
}
|
|
36
|
+
if (name === null) {
|
|
37
|
+
const m = line.match(/\*([^,]+)(?:,.*)?/)
|
|
38
|
+
if (!m) {
|
|
39
|
+
throw new Error("Bad header for .pat file content")
|
|
40
|
+
}
|
|
41
|
+
name = m[1]
|
|
42
|
+
continue
|
|
43
|
+
}
|
|
44
|
+
const commentPos = line.indexOf(";")
|
|
45
|
+
if (commentPos != -1) {
|
|
46
|
+
line = line.substring(0, commentPos).trim()
|
|
47
|
+
}
|
|
48
|
+
let params = line.split(/\s*,\s*/)
|
|
49
|
+
/* Tolerate trailing comma. */
|
|
50
|
+
if (params[params.length - 1] == "") {
|
|
51
|
+
params.length = params.length - 1
|
|
52
|
+
}
|
|
53
|
+
params = params.map(s => {
|
|
54
|
+
const x = parseFloat(s)
|
|
55
|
+
if (isNaN(x)) {
|
|
56
|
+
throw new Error("Failed to parse number in .pat file: " + s)
|
|
57
|
+
}
|
|
58
|
+
return x
|
|
59
|
+
})
|
|
60
|
+
const lineDef = {
|
|
61
|
+
angle: params[0] * Math.PI / 180,
|
|
62
|
+
base: new Vector2(params[1], params[2]),
|
|
63
|
+
offset: new Vector2(params[3], params[4])
|
|
64
|
+
}
|
|
65
|
+
if (params.length > 5) {
|
|
66
|
+
lineDef.dashes = params.slice(5)
|
|
67
|
+
}
|
|
68
|
+
lineDefs.push(lineDef)
|
|
69
|
+
}
|
|
70
|
+
return new Pattern(lineDefs, name)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const patternsRegistryMetric = new Map()
|
|
75
|
+
const patternsRegistryImperial = new Map()
|
|
76
|
+
|
|
77
|
+
/** @param {Pattern} pattern */
|
|
78
|
+
export function RegisterPattern(pattern, isMetric = true) {
|
|
79
|
+
if (!pattern.name) {
|
|
80
|
+
throw new Error("Anonymous pattern cannot be registered")
|
|
81
|
+
}
|
|
82
|
+
const name = pattern.name.toUpperCase()
|
|
83
|
+
const registry = isMetric ? patternsRegistryMetric : patternsRegistryImperial
|
|
84
|
+
if (registry.has(name)) {
|
|
85
|
+
console.warn(`Pattern with name ${name} is already registered`)
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
registry.set(name, pattern)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** @return {?Pattern} */
|
|
92
|
+
export function LookupPattern(name, isMetric = true) {
|
|
93
|
+
return (isMetric ? patternsRegistryMetric : patternsRegistryImperial).get(name.toUpperCase())
|
|
94
|
+
}
|
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
/** Based on bintrees package (https://github.com/vadimg/js_bintrees). Fixed web-worker support. */
|
|
2
|
+
|
|
3
|
+
export const RBTree = (function(window) {
|
|
4
|
+
var global = window;
|
|
5
|
+
var require = function(name) {
|
|
6
|
+
var fn = require.m[name];
|
|
7
|
+
if (fn.mod) {
|
|
8
|
+
return fn.mod.exports;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
var mod = fn.mod = { exports: {} };
|
|
12
|
+
fn(mod, mod.exports);
|
|
13
|
+
return mod.exports;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
require.m = {};
|
|
17
|
+
require.m['./treebase'] = function(module, exports) {
|
|
18
|
+
|
|
19
|
+
function TreeBase() {}
|
|
20
|
+
|
|
21
|
+
// removes all nodes from the tree
|
|
22
|
+
TreeBase.prototype.clear = function() {
|
|
23
|
+
this._root = null;
|
|
24
|
+
this.size = 0;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// returns node data if found, null otherwise
|
|
28
|
+
TreeBase.prototype.find = function(data) {
|
|
29
|
+
var res = this._root;
|
|
30
|
+
|
|
31
|
+
while(res !== null) {
|
|
32
|
+
var c = this._comparator(data, res.data);
|
|
33
|
+
if(c === 0) {
|
|
34
|
+
return res.data;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
res = res.get_child(c > 0);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return null;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// returns iterator to node if found, null otherwise
|
|
45
|
+
TreeBase.prototype.findIter = function(data) {
|
|
46
|
+
var res = this._root;
|
|
47
|
+
var iter = this.iterator();
|
|
48
|
+
|
|
49
|
+
while(res !== null) {
|
|
50
|
+
var c = this._comparator(data, res.data);
|
|
51
|
+
if(c === 0) {
|
|
52
|
+
iter._cursor = res;
|
|
53
|
+
return iter;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
iter._ancestors.push(res);
|
|
57
|
+
res = res.get_child(c > 0);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return null;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Returns an iterator to the tree node at or immediately after the item
|
|
65
|
+
TreeBase.prototype.lowerBound = function(item) {
|
|
66
|
+
var cur = this._root;
|
|
67
|
+
var iter = this.iterator();
|
|
68
|
+
var cmp = this._comparator;
|
|
69
|
+
|
|
70
|
+
while(cur !== null) {
|
|
71
|
+
var c = cmp(item, cur.data);
|
|
72
|
+
if(c === 0) {
|
|
73
|
+
iter._cursor = cur;
|
|
74
|
+
return iter;
|
|
75
|
+
}
|
|
76
|
+
iter._ancestors.push(cur);
|
|
77
|
+
cur = cur.get_child(c > 0);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
for(var i=iter._ancestors.length - 1; i >= 0; --i) {
|
|
81
|
+
cur = iter._ancestors[i];
|
|
82
|
+
if(cmp(item, cur.data) < 0) {
|
|
83
|
+
iter._cursor = cur;
|
|
84
|
+
iter._ancestors.length = i;
|
|
85
|
+
return iter;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
iter._ancestors.length = 0;
|
|
90
|
+
return iter;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// Returns an iterator to the tree node immediately after the item
|
|
94
|
+
TreeBase.prototype.upperBound = function(item) {
|
|
95
|
+
var iter = this.lowerBound(item);
|
|
96
|
+
var cmp = this._comparator;
|
|
97
|
+
|
|
98
|
+
while(iter.data() !== null && cmp(iter.data(), item) === 0) {
|
|
99
|
+
iter.next();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return iter;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// returns null if tree is empty
|
|
106
|
+
TreeBase.prototype.min = function() {
|
|
107
|
+
var res = this._root;
|
|
108
|
+
if(res === null) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
while(res.left !== null) {
|
|
113
|
+
res = res.left;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return res.data;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// returns null if tree is empty
|
|
120
|
+
TreeBase.prototype.max = function() {
|
|
121
|
+
var res = this._root;
|
|
122
|
+
if(res === null) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
while(res.right !== null) {
|
|
127
|
+
res = res.right;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return res.data;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// returns a null iterator
|
|
134
|
+
// call next() or prev() to point to an element
|
|
135
|
+
TreeBase.prototype.iterator = function() {
|
|
136
|
+
return new Iterator(this);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// calls cb on each node's data, in order
|
|
140
|
+
TreeBase.prototype.each = function(cb) {
|
|
141
|
+
var it=this.iterator(), data;
|
|
142
|
+
while((data = it.next()) !== null) {
|
|
143
|
+
cb(data);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// calls cb on each node's data, in reverse order
|
|
148
|
+
TreeBase.prototype.reach = function(cb) {
|
|
149
|
+
var it=this.iterator(), data;
|
|
150
|
+
while((data = it.prev()) !== null) {
|
|
151
|
+
cb(data);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
function Iterator(tree) {
|
|
157
|
+
this._tree = tree;
|
|
158
|
+
this._ancestors = [];
|
|
159
|
+
this._cursor = null;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
Iterator.prototype.data = function() {
|
|
163
|
+
return this._cursor !== null ? this._cursor.data : null;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// if null-iterator, returns first node
|
|
167
|
+
// otherwise, returns next node
|
|
168
|
+
Iterator.prototype.next = function() {
|
|
169
|
+
if(this._cursor === null) {
|
|
170
|
+
var root = this._tree._root;
|
|
171
|
+
if(root !== null) {
|
|
172
|
+
this._minNode(root);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
if(this._cursor.right === null) {
|
|
177
|
+
// no greater node in subtree, go up to parent
|
|
178
|
+
// if coming from a right child, continue up the stack
|
|
179
|
+
var save;
|
|
180
|
+
do {
|
|
181
|
+
save = this._cursor;
|
|
182
|
+
if(this._ancestors.length) {
|
|
183
|
+
this._cursor = this._ancestors.pop();
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
this._cursor = null;
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
} while(this._cursor.right === save);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// get the next node from the subtree
|
|
193
|
+
this._ancestors.push(this._cursor);
|
|
194
|
+
this._minNode(this._cursor.right);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return this._cursor !== null ? this._cursor.data : null;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
// if null-iterator, returns last node
|
|
201
|
+
// otherwise, returns previous node
|
|
202
|
+
Iterator.prototype.prev = function() {
|
|
203
|
+
if(this._cursor === null) {
|
|
204
|
+
var root = this._tree._root;
|
|
205
|
+
if(root !== null) {
|
|
206
|
+
this._maxNode(root);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
if(this._cursor.left === null) {
|
|
211
|
+
var save;
|
|
212
|
+
do {
|
|
213
|
+
save = this._cursor;
|
|
214
|
+
if(this._ancestors.length) {
|
|
215
|
+
this._cursor = this._ancestors.pop();
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
this._cursor = null;
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
} while(this._cursor.left === save);
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
this._ancestors.push(this._cursor);
|
|
225
|
+
this._maxNode(this._cursor.left);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return this._cursor !== null ? this._cursor.data : null;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
Iterator.prototype._minNode = function(start) {
|
|
232
|
+
while(start.left !== null) {
|
|
233
|
+
this._ancestors.push(start);
|
|
234
|
+
start = start.left;
|
|
235
|
+
}
|
|
236
|
+
this._cursor = start;
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
Iterator.prototype._maxNode = function(start) {
|
|
240
|
+
while(start.right !== null) {
|
|
241
|
+
this._ancestors.push(start);
|
|
242
|
+
start = start.right;
|
|
243
|
+
}
|
|
244
|
+
this._cursor = start;
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
module.exports = TreeBase;
|
|
248
|
+
|
|
249
|
+
};
|
|
250
|
+
require.m['__main__'] = function(module, exports) {
|
|
251
|
+
|
|
252
|
+
var TreeBase = require('./treebase');
|
|
253
|
+
|
|
254
|
+
function Node(data) {
|
|
255
|
+
this.data = data;
|
|
256
|
+
this.left = null;
|
|
257
|
+
this.right = null;
|
|
258
|
+
this.red = true;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
Node.prototype.get_child = function(dir) {
|
|
262
|
+
return dir ? this.right : this.left;
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
Node.prototype.set_child = function(dir, val) {
|
|
266
|
+
if(dir) {
|
|
267
|
+
this.right = val;
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
this.left = val;
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
function RBTree(comparator) {
|
|
275
|
+
this._root = null;
|
|
276
|
+
this._comparator = comparator;
|
|
277
|
+
this.size = 0;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
RBTree.prototype = new TreeBase();
|
|
281
|
+
|
|
282
|
+
// returns true if inserted, false if duplicate
|
|
283
|
+
RBTree.prototype.insert = function(data) {
|
|
284
|
+
var ret = false;
|
|
285
|
+
|
|
286
|
+
if(this._root === null) {
|
|
287
|
+
// empty tree
|
|
288
|
+
this._root = new Node(data);
|
|
289
|
+
ret = true;
|
|
290
|
+
this.size++;
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
var head = new Node(undefined); // fake tree root
|
|
294
|
+
|
|
295
|
+
var dir = 0;
|
|
296
|
+
var last = 0;
|
|
297
|
+
|
|
298
|
+
// setup
|
|
299
|
+
var gp = null; // grandparent
|
|
300
|
+
var ggp = head; // grand-grand-parent
|
|
301
|
+
var p = null; // parent
|
|
302
|
+
var node = this._root;
|
|
303
|
+
ggp.right = this._root;
|
|
304
|
+
|
|
305
|
+
// search down
|
|
306
|
+
while(true) {
|
|
307
|
+
if(node === null) {
|
|
308
|
+
// insert new node at the bottom
|
|
309
|
+
node = new Node(data);
|
|
310
|
+
p.set_child(dir, node);
|
|
311
|
+
ret = true;
|
|
312
|
+
this.size++;
|
|
313
|
+
}
|
|
314
|
+
else if(is_red(node.left) && is_red(node.right)) {
|
|
315
|
+
// color flip
|
|
316
|
+
node.red = true;
|
|
317
|
+
node.left.red = false;
|
|
318
|
+
node.right.red = false;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// fix red violation
|
|
322
|
+
if(is_red(node) && is_red(p)) {
|
|
323
|
+
var dir2 = ggp.right === gp;
|
|
324
|
+
|
|
325
|
+
if(node === p.get_child(last)) {
|
|
326
|
+
ggp.set_child(dir2, single_rotate(gp, !last));
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
ggp.set_child(dir2, double_rotate(gp, !last));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
var cmp = this._comparator(node.data, data);
|
|
334
|
+
|
|
335
|
+
// stop if found
|
|
336
|
+
if(cmp === 0) {
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
last = dir;
|
|
341
|
+
dir = cmp < 0;
|
|
342
|
+
|
|
343
|
+
// update helpers
|
|
344
|
+
if(gp !== null) {
|
|
345
|
+
ggp = gp;
|
|
346
|
+
}
|
|
347
|
+
gp = p;
|
|
348
|
+
p = node;
|
|
349
|
+
node = node.get_child(dir);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// update root
|
|
353
|
+
this._root = head.right;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// make root black
|
|
357
|
+
this._root.red = false;
|
|
358
|
+
|
|
359
|
+
return ret;
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
// returns true if removed, false if not found
|
|
363
|
+
RBTree.prototype.remove = function(data) {
|
|
364
|
+
if(this._root === null) {
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
var head = new Node(undefined); // fake tree root
|
|
369
|
+
var node = head;
|
|
370
|
+
node.right = this._root;
|
|
371
|
+
var p = null; // parent
|
|
372
|
+
var gp = null; // grand parent
|
|
373
|
+
var found = null; // found item
|
|
374
|
+
var dir = 1;
|
|
375
|
+
|
|
376
|
+
while(node.get_child(dir) !== null) {
|
|
377
|
+
var last = dir;
|
|
378
|
+
|
|
379
|
+
// update helpers
|
|
380
|
+
gp = p;
|
|
381
|
+
p = node;
|
|
382
|
+
node = node.get_child(dir);
|
|
383
|
+
|
|
384
|
+
var cmp = this._comparator(data, node.data);
|
|
385
|
+
|
|
386
|
+
dir = cmp > 0;
|
|
387
|
+
|
|
388
|
+
// save found node
|
|
389
|
+
if(cmp === 0) {
|
|
390
|
+
found = node;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// push the red node down
|
|
394
|
+
if(!is_red(node) && !is_red(node.get_child(dir))) {
|
|
395
|
+
if(is_red(node.get_child(!dir))) {
|
|
396
|
+
var sr = single_rotate(node, dir);
|
|
397
|
+
p.set_child(last, sr);
|
|
398
|
+
p = sr;
|
|
399
|
+
}
|
|
400
|
+
else if(!is_red(node.get_child(!dir))) {
|
|
401
|
+
var sibling = p.get_child(!last);
|
|
402
|
+
if(sibling !== null) {
|
|
403
|
+
if(!is_red(sibling.get_child(!last)) && !is_red(sibling.get_child(last))) {
|
|
404
|
+
// color flip
|
|
405
|
+
p.red = false;
|
|
406
|
+
sibling.red = true;
|
|
407
|
+
node.red = true;
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
var dir2 = gp.right === p;
|
|
411
|
+
|
|
412
|
+
if(is_red(sibling.get_child(last))) {
|
|
413
|
+
gp.set_child(dir2, double_rotate(p, last));
|
|
414
|
+
}
|
|
415
|
+
else if(is_red(sibling.get_child(!last))) {
|
|
416
|
+
gp.set_child(dir2, single_rotate(p, last));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// ensure correct coloring
|
|
420
|
+
var gpc = gp.get_child(dir2);
|
|
421
|
+
gpc.red = true;
|
|
422
|
+
node.red = true;
|
|
423
|
+
gpc.left.red = false;
|
|
424
|
+
gpc.right.red = false;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// replace and remove if found
|
|
432
|
+
if(found !== null) {
|
|
433
|
+
found.data = node.data;
|
|
434
|
+
p.set_child(p.right === node, node.get_child(node.left === null));
|
|
435
|
+
this.size--;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// update root and make it black
|
|
439
|
+
this._root = head.right;
|
|
440
|
+
if(this._root !== null) {
|
|
441
|
+
this._root.red = false;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return found !== null;
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
function is_red(node) {
|
|
448
|
+
return node !== null && node.red;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function single_rotate(root, dir) {
|
|
452
|
+
var save = root.get_child(!dir);
|
|
453
|
+
|
|
454
|
+
root.set_child(!dir, save.get_child(dir));
|
|
455
|
+
save.set_child(dir, root);
|
|
456
|
+
|
|
457
|
+
root.red = true;
|
|
458
|
+
save.red = false;
|
|
459
|
+
|
|
460
|
+
return save;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function double_rotate(root, dir) {
|
|
464
|
+
root.set_child(!dir, single_rotate(root.get_child(!dir), !dir));
|
|
465
|
+
return single_rotate(root, dir);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
module.exports = RBTree;
|
|
469
|
+
};
|
|
470
|
+
return require('__main__');
|
|
471
|
+
})(self);
|