@footgun/cobalt 0.3.3 → 0.5.0
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/CHANGELOG.md +7 -2
- package/bundle.js +9 -9
- package/examples/07-sdl/main.js +0 -1
- package/examples/07-sdl/package.json +2 -2
- package/examples/09-sdl-polar-meters/package.json +3 -3
- package/package.json +8 -3
- package/packages/box-intersect/index.js +138 -0
- package/packages/box-intersect/lib/brute.js +144 -0
- package/packages/box-intersect/lib/intersect.js +494 -0
- package/packages/box-intersect/lib/median.js +142 -0
- package/packages/box-intersect/lib/partition.js +20 -0
- package/packages/box-intersect/lib/sort.js +236 -0
- package/packages/box-intersect/lib/sweep.js +434 -0
- package/packages/box-intersect/package.json +24 -0
- package/packages/clean-pslg/clean-pslg.js +381 -0
- package/packages/clean-pslg/lib/rat-seg-intersect.js +42 -0
- package/packages/clean-pslg/package.json +29 -0
- package/packages/poly-to-pslg/package.json +15 -0
- package/packages/poly-to-pslg/poly-to-pslg.js +51 -0
- package/packages/typedarray-pool/package.json +17 -0
- package/packages/typedarray-pool/pool.js +225 -0
- package/src/primitives/primitives.js +13 -3
- package/src/primitives/public-api.js +44 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
//This code is extracted from ndarray-sort
|
|
4
|
+
//It is inlined here as a temporary workaround
|
|
5
|
+
|
|
6
|
+
module.exports = wrapper;
|
|
7
|
+
|
|
8
|
+
var INSERT_SORT_CUTOFF = 32
|
|
9
|
+
|
|
10
|
+
function wrapper(data, n0) {
|
|
11
|
+
if (n0 <= 4*INSERT_SORT_CUTOFF) {
|
|
12
|
+
insertionSort(0, n0 - 1, data);
|
|
13
|
+
} else {
|
|
14
|
+
quickSort(0, n0 - 1, data);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function insertionSort(left, right, data) {
|
|
19
|
+
var ptr = 2*(left+1)
|
|
20
|
+
for(var i=left+1; i<=right; ++i) {
|
|
21
|
+
var a = data[ptr++]
|
|
22
|
+
var b = data[ptr++]
|
|
23
|
+
var j = i
|
|
24
|
+
var jptr = ptr-2
|
|
25
|
+
while(j-- > left) {
|
|
26
|
+
var x = data[jptr-2]
|
|
27
|
+
var y = data[jptr-1]
|
|
28
|
+
if(x < a) {
|
|
29
|
+
break
|
|
30
|
+
} else if(x === a && y < b) {
|
|
31
|
+
break
|
|
32
|
+
}
|
|
33
|
+
data[jptr] = x
|
|
34
|
+
data[jptr+1] = y
|
|
35
|
+
jptr -= 2
|
|
36
|
+
}
|
|
37
|
+
data[jptr] = a
|
|
38
|
+
data[jptr+1] = b
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function swap(i, j, data) {
|
|
43
|
+
i *= 2
|
|
44
|
+
j *= 2
|
|
45
|
+
var x = data[i]
|
|
46
|
+
var y = data[i+1]
|
|
47
|
+
data[i] = data[j]
|
|
48
|
+
data[i+1] = data[j+1]
|
|
49
|
+
data[j] = x
|
|
50
|
+
data[j+1] = y
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function move(i, j, data) {
|
|
54
|
+
i *= 2
|
|
55
|
+
j *= 2
|
|
56
|
+
data[i] = data[j]
|
|
57
|
+
data[i+1] = data[j+1]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function rotate(i, j, k, data) {
|
|
61
|
+
i *= 2
|
|
62
|
+
j *= 2
|
|
63
|
+
k *= 2
|
|
64
|
+
var x = data[i]
|
|
65
|
+
var y = data[i+1]
|
|
66
|
+
data[i] = data[j]
|
|
67
|
+
data[i+1] = data[j+1]
|
|
68
|
+
data[j] = data[k]
|
|
69
|
+
data[j+1] = data[k+1]
|
|
70
|
+
data[k] = x
|
|
71
|
+
data[k+1] = y
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function shufflePivot(i, j, px, py, data) {
|
|
75
|
+
i *= 2
|
|
76
|
+
j *= 2
|
|
77
|
+
data[i] = data[j]
|
|
78
|
+
data[j] = px
|
|
79
|
+
data[i+1] = data[j+1]
|
|
80
|
+
data[j+1] = py
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function compare(i, j, data) {
|
|
84
|
+
i *= 2
|
|
85
|
+
j *= 2
|
|
86
|
+
var x = data[i],
|
|
87
|
+
y = data[j]
|
|
88
|
+
if(x < y) {
|
|
89
|
+
return false
|
|
90
|
+
} else if(x === y) {
|
|
91
|
+
return data[i+1] > data[j+1]
|
|
92
|
+
}
|
|
93
|
+
return true
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function comparePivot(i, y, b, data) {
|
|
97
|
+
i *= 2
|
|
98
|
+
var x = data[i]
|
|
99
|
+
if(x < y) {
|
|
100
|
+
return true
|
|
101
|
+
} else if(x === y) {
|
|
102
|
+
return data[i+1] < b
|
|
103
|
+
}
|
|
104
|
+
return false
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function quickSort(left, right, data) {
|
|
108
|
+
var sixth = (right - left + 1) / 6 | 0,
|
|
109
|
+
index1 = left + sixth,
|
|
110
|
+
index5 = right - sixth,
|
|
111
|
+
index3 = left + right >> 1,
|
|
112
|
+
index2 = index3 - sixth,
|
|
113
|
+
index4 = index3 + sixth,
|
|
114
|
+
el1 = index1,
|
|
115
|
+
el2 = index2,
|
|
116
|
+
el3 = index3,
|
|
117
|
+
el4 = index4,
|
|
118
|
+
el5 = index5,
|
|
119
|
+
less = left + 1,
|
|
120
|
+
great = right - 1,
|
|
121
|
+
tmp = 0
|
|
122
|
+
if(compare(el1, el2, data)) {
|
|
123
|
+
tmp = el1
|
|
124
|
+
el1 = el2
|
|
125
|
+
el2 = tmp
|
|
126
|
+
}
|
|
127
|
+
if(compare(el4, el5, data)) {
|
|
128
|
+
tmp = el4
|
|
129
|
+
el4 = el5
|
|
130
|
+
el5 = tmp
|
|
131
|
+
}
|
|
132
|
+
if(compare(el1, el3, data)) {
|
|
133
|
+
tmp = el1
|
|
134
|
+
el1 = el3
|
|
135
|
+
el3 = tmp
|
|
136
|
+
}
|
|
137
|
+
if(compare(el2, el3, data)) {
|
|
138
|
+
tmp = el2
|
|
139
|
+
el2 = el3
|
|
140
|
+
el3 = tmp
|
|
141
|
+
}
|
|
142
|
+
if(compare(el1, el4, data)) {
|
|
143
|
+
tmp = el1
|
|
144
|
+
el1 = el4
|
|
145
|
+
el4 = tmp
|
|
146
|
+
}
|
|
147
|
+
if(compare(el3, el4, data)) {
|
|
148
|
+
tmp = el3
|
|
149
|
+
el3 = el4
|
|
150
|
+
el4 = tmp
|
|
151
|
+
}
|
|
152
|
+
if(compare(el2, el5, data)) {
|
|
153
|
+
tmp = el2
|
|
154
|
+
el2 = el5
|
|
155
|
+
el5 = tmp
|
|
156
|
+
}
|
|
157
|
+
if(compare(el2, el3, data)) {
|
|
158
|
+
tmp = el2
|
|
159
|
+
el2 = el3
|
|
160
|
+
el3 = tmp
|
|
161
|
+
}
|
|
162
|
+
if(compare(el4, el5, data)) {
|
|
163
|
+
tmp = el4
|
|
164
|
+
el4 = el5
|
|
165
|
+
el5 = tmp
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
var pivot1X = data[2*el2]
|
|
169
|
+
var pivot1Y = data[2*el2+1]
|
|
170
|
+
var pivot2X = data[2*el4]
|
|
171
|
+
var pivot2Y = data[2*el4+1]
|
|
172
|
+
|
|
173
|
+
var ptr0 = 2 * el1;
|
|
174
|
+
var ptr2 = 2 * el3;
|
|
175
|
+
var ptr4 = 2 * el5;
|
|
176
|
+
var ptr5 = 2 * index1;
|
|
177
|
+
var ptr6 = 2 * index3;
|
|
178
|
+
var ptr7 = 2 * index5;
|
|
179
|
+
for (var i1 = 0; i1 < 2; ++i1) {
|
|
180
|
+
var x = data[ptr0+i1];
|
|
181
|
+
var y = data[ptr2+i1];
|
|
182
|
+
var z = data[ptr4+i1];
|
|
183
|
+
data[ptr5+i1] = x;
|
|
184
|
+
data[ptr6+i1] = y;
|
|
185
|
+
data[ptr7+i1] = z;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
move(index2, left, data)
|
|
189
|
+
move(index4, right, data)
|
|
190
|
+
for (var k = less; k <= great; ++k) {
|
|
191
|
+
if (comparePivot(k, pivot1X, pivot1Y, data)) {
|
|
192
|
+
if (k !== less) {
|
|
193
|
+
swap(k, less, data)
|
|
194
|
+
}
|
|
195
|
+
++less;
|
|
196
|
+
} else {
|
|
197
|
+
if (!comparePivot(k, pivot2X, pivot2Y, data)) {
|
|
198
|
+
while (true) {
|
|
199
|
+
if (!comparePivot(great, pivot2X, pivot2Y, data)) {
|
|
200
|
+
if (--great < k) {
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
continue;
|
|
204
|
+
} else {
|
|
205
|
+
if (comparePivot(great, pivot1X, pivot1Y, data)) {
|
|
206
|
+
rotate(k, less, great, data)
|
|
207
|
+
++less;
|
|
208
|
+
--great;
|
|
209
|
+
} else {
|
|
210
|
+
swap(k, great, data)
|
|
211
|
+
--great;
|
|
212
|
+
}
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
shufflePivot(left, less-1, pivot1X, pivot1Y, data)
|
|
220
|
+
shufflePivot(right, great+1, pivot2X, pivot2Y, data)
|
|
221
|
+
if (less - 2 - left <= INSERT_SORT_CUTOFF) {
|
|
222
|
+
insertionSort(left, less - 2, data);
|
|
223
|
+
} else {
|
|
224
|
+
quickSort(left, less - 2, data);
|
|
225
|
+
}
|
|
226
|
+
if (right - (great + 2) <= INSERT_SORT_CUTOFF) {
|
|
227
|
+
insertionSort(great + 2, right, data);
|
|
228
|
+
} else {
|
|
229
|
+
quickSort(great + 2, right, data);
|
|
230
|
+
}
|
|
231
|
+
if (great - less <= INSERT_SORT_CUTOFF) {
|
|
232
|
+
insertionSort(less, great, data);
|
|
233
|
+
} else {
|
|
234
|
+
quickSort(less, great, data);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
init: sqInit,
|
|
5
|
+
sweepBipartite: sweepBipartite,
|
|
6
|
+
sweepComplete: sweepComplete,
|
|
7
|
+
scanBipartite: scanBipartite,
|
|
8
|
+
scanComplete: scanComplete
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
var pool = require('typedarray-pool')
|
|
12
|
+
var bits = require('bit-twiddle')
|
|
13
|
+
var isort = require('./sort')
|
|
14
|
+
|
|
15
|
+
//Flag for blue
|
|
16
|
+
var BLUE_FLAG = (1<<28)
|
|
17
|
+
|
|
18
|
+
//1D sweep event queue stuff (use pool to save space)
|
|
19
|
+
var INIT_CAPACITY = 1024
|
|
20
|
+
var RED_SWEEP_QUEUE = pool.mallocInt32(INIT_CAPACITY)
|
|
21
|
+
var RED_SWEEP_INDEX = pool.mallocInt32(INIT_CAPACITY)
|
|
22
|
+
var BLUE_SWEEP_QUEUE = pool.mallocInt32(INIT_CAPACITY)
|
|
23
|
+
var BLUE_SWEEP_INDEX = pool.mallocInt32(INIT_CAPACITY)
|
|
24
|
+
var COMMON_SWEEP_QUEUE = pool.mallocInt32(INIT_CAPACITY)
|
|
25
|
+
var COMMON_SWEEP_INDEX = pool.mallocInt32(INIT_CAPACITY)
|
|
26
|
+
var SWEEP_EVENTS = pool.mallocDouble(INIT_CAPACITY * 8)
|
|
27
|
+
|
|
28
|
+
//Reserves memory for the 1D sweep data structures
|
|
29
|
+
function sqInit(count) {
|
|
30
|
+
var rcount = bits.nextPow2(count)
|
|
31
|
+
if(RED_SWEEP_QUEUE.length < rcount) {
|
|
32
|
+
pool.free(RED_SWEEP_QUEUE)
|
|
33
|
+
RED_SWEEP_QUEUE = pool.mallocInt32(rcount)
|
|
34
|
+
}
|
|
35
|
+
if(RED_SWEEP_INDEX.length < rcount) {
|
|
36
|
+
pool.free(RED_SWEEP_INDEX)
|
|
37
|
+
RED_SWEEP_INDEX = pool.mallocInt32(rcount)
|
|
38
|
+
}
|
|
39
|
+
if(BLUE_SWEEP_QUEUE.length < rcount) {
|
|
40
|
+
pool.free(BLUE_SWEEP_QUEUE)
|
|
41
|
+
BLUE_SWEEP_QUEUE = pool.mallocInt32(rcount)
|
|
42
|
+
}
|
|
43
|
+
if(BLUE_SWEEP_INDEX.length < rcount) {
|
|
44
|
+
pool.free(BLUE_SWEEP_INDEX)
|
|
45
|
+
BLUE_SWEEP_INDEX = pool.mallocInt32(rcount)
|
|
46
|
+
}
|
|
47
|
+
if(COMMON_SWEEP_QUEUE.length < rcount) {
|
|
48
|
+
pool.free(COMMON_SWEEP_QUEUE)
|
|
49
|
+
COMMON_SWEEP_QUEUE = pool.mallocInt32(rcount)
|
|
50
|
+
}
|
|
51
|
+
if(COMMON_SWEEP_INDEX.length < rcount) {
|
|
52
|
+
pool.free(COMMON_SWEEP_INDEX)
|
|
53
|
+
COMMON_SWEEP_INDEX = pool.mallocInt32(rcount)
|
|
54
|
+
}
|
|
55
|
+
var eventLength = 8 * rcount
|
|
56
|
+
if(SWEEP_EVENTS.length < eventLength) {
|
|
57
|
+
pool.free(SWEEP_EVENTS)
|
|
58
|
+
SWEEP_EVENTS = pool.mallocDouble(eventLength)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//Remove an item from the active queue in O(1)
|
|
63
|
+
function sqPop(queue, index, count, item) {
|
|
64
|
+
var idx = index[item]
|
|
65
|
+
var top = queue[count-1]
|
|
66
|
+
queue[idx] = top
|
|
67
|
+
index[top] = idx
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
//Insert an item into the active queue in O(1)
|
|
71
|
+
function sqPush(queue, index, count, item) {
|
|
72
|
+
queue[count] = item
|
|
73
|
+
index[item] = count
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
//Recursion base case: use 1D sweep algorithm
|
|
77
|
+
function sweepBipartite(
|
|
78
|
+
d, visit,
|
|
79
|
+
redStart, redEnd, red, redIndex,
|
|
80
|
+
blueStart, blueEnd, blue, blueIndex) {
|
|
81
|
+
|
|
82
|
+
//store events as pairs [coordinate, idx]
|
|
83
|
+
//
|
|
84
|
+
// red create: -(idx+1)
|
|
85
|
+
// red destroy: idx
|
|
86
|
+
// blue create: -(idx+BLUE_FLAG)
|
|
87
|
+
// blue destroy: idx+BLUE_FLAG
|
|
88
|
+
//
|
|
89
|
+
var ptr = 0
|
|
90
|
+
var elemSize = 2*d
|
|
91
|
+
var istart = d-1
|
|
92
|
+
var iend = elemSize-1
|
|
93
|
+
|
|
94
|
+
for(var i=redStart; i<redEnd; ++i) {
|
|
95
|
+
var idx = redIndex[i]
|
|
96
|
+
var redOffset = elemSize*i
|
|
97
|
+
SWEEP_EVENTS[ptr++] = red[redOffset+istart]
|
|
98
|
+
SWEEP_EVENTS[ptr++] = -(idx+1)
|
|
99
|
+
SWEEP_EVENTS[ptr++] = red[redOffset+iend]
|
|
100
|
+
SWEEP_EVENTS[ptr++] = idx
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
for(var i=blueStart; i<blueEnd; ++i) {
|
|
104
|
+
var idx = blueIndex[i]+BLUE_FLAG
|
|
105
|
+
var blueOffset = elemSize*i
|
|
106
|
+
SWEEP_EVENTS[ptr++] = blue[blueOffset+istart]
|
|
107
|
+
SWEEP_EVENTS[ptr++] = -idx
|
|
108
|
+
SWEEP_EVENTS[ptr++] = blue[blueOffset+iend]
|
|
109
|
+
SWEEP_EVENTS[ptr++] = idx
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
//process events from left->right
|
|
113
|
+
var n = ptr >>> 1
|
|
114
|
+
isort(SWEEP_EVENTS, n)
|
|
115
|
+
|
|
116
|
+
var redActive = 0
|
|
117
|
+
var blueActive = 0
|
|
118
|
+
for(var i=0; i<n; ++i) {
|
|
119
|
+
var e = SWEEP_EVENTS[2*i+1]|0
|
|
120
|
+
if(e >= BLUE_FLAG) {
|
|
121
|
+
//blue destroy event
|
|
122
|
+
e = (e-BLUE_FLAG)|0
|
|
123
|
+
sqPop(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive--, e)
|
|
124
|
+
} else if(e >= 0) {
|
|
125
|
+
//red destroy event
|
|
126
|
+
sqPop(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive--, e)
|
|
127
|
+
} else if(e <= -BLUE_FLAG) {
|
|
128
|
+
//blue create event
|
|
129
|
+
e = (-e-BLUE_FLAG)|0
|
|
130
|
+
for(var j=0; j<redActive; ++j) {
|
|
131
|
+
var retval = visit(RED_SWEEP_QUEUE[j], e)
|
|
132
|
+
if(retval !== void 0) {
|
|
133
|
+
return retval
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
sqPush(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive++, e)
|
|
137
|
+
} else {
|
|
138
|
+
//red create event
|
|
139
|
+
e = (-e-1)|0
|
|
140
|
+
for(var j=0; j<blueActive; ++j) {
|
|
141
|
+
var retval = visit(e, BLUE_SWEEP_QUEUE[j])
|
|
142
|
+
if(retval !== void 0) {
|
|
143
|
+
return retval
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
sqPush(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive++, e)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
//Complete sweep
|
|
152
|
+
function sweepComplete(d, visit,
|
|
153
|
+
redStart, redEnd, red, redIndex,
|
|
154
|
+
blueStart, blueEnd, blue, blueIndex) {
|
|
155
|
+
|
|
156
|
+
var ptr = 0
|
|
157
|
+
var elemSize = 2*d
|
|
158
|
+
var istart = d-1
|
|
159
|
+
var iend = elemSize-1
|
|
160
|
+
|
|
161
|
+
for(var i=redStart; i<redEnd; ++i) {
|
|
162
|
+
var idx = (redIndex[i]+1)<<1
|
|
163
|
+
var redOffset = elemSize*i
|
|
164
|
+
SWEEP_EVENTS[ptr++] = red[redOffset+istart]
|
|
165
|
+
SWEEP_EVENTS[ptr++] = -idx
|
|
166
|
+
SWEEP_EVENTS[ptr++] = red[redOffset+iend]
|
|
167
|
+
SWEEP_EVENTS[ptr++] = idx
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
for(var i=blueStart; i<blueEnd; ++i) {
|
|
171
|
+
var idx = (blueIndex[i]+1)<<1
|
|
172
|
+
var blueOffset = elemSize*i
|
|
173
|
+
SWEEP_EVENTS[ptr++] = blue[blueOffset+istart]
|
|
174
|
+
SWEEP_EVENTS[ptr++] = (-idx)|1
|
|
175
|
+
SWEEP_EVENTS[ptr++] = blue[blueOffset+iend]
|
|
176
|
+
SWEEP_EVENTS[ptr++] = idx|1
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
//process events from left->right
|
|
180
|
+
var n = ptr >>> 1
|
|
181
|
+
isort(SWEEP_EVENTS, n)
|
|
182
|
+
|
|
183
|
+
var redActive = 0
|
|
184
|
+
var blueActive = 0
|
|
185
|
+
var commonActive = 0
|
|
186
|
+
for(var i=0; i<n; ++i) {
|
|
187
|
+
var e = SWEEP_EVENTS[2*i+1]|0
|
|
188
|
+
var color = e&1
|
|
189
|
+
if(i < n-1 && (e>>1) === (SWEEP_EVENTS[2*i+3]>>1)) {
|
|
190
|
+
color = 2
|
|
191
|
+
i += 1
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if(e < 0) {
|
|
195
|
+
//Create event
|
|
196
|
+
var id = -(e>>1) - 1
|
|
197
|
+
|
|
198
|
+
//Intersect with common
|
|
199
|
+
for(var j=0; j<commonActive; ++j) {
|
|
200
|
+
var retval = visit(COMMON_SWEEP_QUEUE[j], id)
|
|
201
|
+
if(retval !== void 0) {
|
|
202
|
+
return retval
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if(color !== 0) {
|
|
207
|
+
//Intersect with red
|
|
208
|
+
for(var j=0; j<redActive; ++j) {
|
|
209
|
+
var retval = visit(RED_SWEEP_QUEUE[j], id)
|
|
210
|
+
if(retval !== void 0) {
|
|
211
|
+
return retval
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if(color !== 1) {
|
|
217
|
+
//Intersect with blue
|
|
218
|
+
for(var j=0; j<blueActive; ++j) {
|
|
219
|
+
var retval = visit(BLUE_SWEEP_QUEUE[j], id)
|
|
220
|
+
if(retval !== void 0) {
|
|
221
|
+
return retval
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if(color === 0) {
|
|
227
|
+
//Red
|
|
228
|
+
sqPush(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive++, id)
|
|
229
|
+
} else if(color === 1) {
|
|
230
|
+
//Blue
|
|
231
|
+
sqPush(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive++, id)
|
|
232
|
+
} else if(color === 2) {
|
|
233
|
+
//Both
|
|
234
|
+
sqPush(COMMON_SWEEP_QUEUE, COMMON_SWEEP_INDEX, commonActive++, id)
|
|
235
|
+
}
|
|
236
|
+
} else {
|
|
237
|
+
//Destroy event
|
|
238
|
+
var id = (e>>1) - 1
|
|
239
|
+
if(color === 0) {
|
|
240
|
+
//Red
|
|
241
|
+
sqPop(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive--, id)
|
|
242
|
+
} else if(color === 1) {
|
|
243
|
+
//Blue
|
|
244
|
+
sqPop(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive--, id)
|
|
245
|
+
} else if(color === 2) {
|
|
246
|
+
//Both
|
|
247
|
+
sqPop(COMMON_SWEEP_QUEUE, COMMON_SWEEP_INDEX, commonActive--, id)
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
//Sweep and prune/scanline algorithm:
|
|
254
|
+
// Scan along axis, detect intersections
|
|
255
|
+
// Brute force all boxes along axis
|
|
256
|
+
function scanBipartite(
|
|
257
|
+
d, axis, visit, flip,
|
|
258
|
+
redStart, redEnd, red, redIndex,
|
|
259
|
+
blueStart, blueEnd, blue, blueIndex) {
|
|
260
|
+
|
|
261
|
+
var ptr = 0
|
|
262
|
+
var elemSize = 2*d
|
|
263
|
+
var istart = axis
|
|
264
|
+
var iend = axis+d
|
|
265
|
+
|
|
266
|
+
var redShift = 1
|
|
267
|
+
var blueShift = 1
|
|
268
|
+
if(flip) {
|
|
269
|
+
blueShift = BLUE_FLAG
|
|
270
|
+
} else {
|
|
271
|
+
redShift = BLUE_FLAG
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
for(var i=redStart; i<redEnd; ++i) {
|
|
275
|
+
var idx = i + redShift
|
|
276
|
+
var redOffset = elemSize*i
|
|
277
|
+
SWEEP_EVENTS[ptr++] = red[redOffset+istart]
|
|
278
|
+
SWEEP_EVENTS[ptr++] = -idx
|
|
279
|
+
SWEEP_EVENTS[ptr++] = red[redOffset+iend]
|
|
280
|
+
SWEEP_EVENTS[ptr++] = idx
|
|
281
|
+
}
|
|
282
|
+
for(var i=blueStart; i<blueEnd; ++i) {
|
|
283
|
+
var idx = i + blueShift
|
|
284
|
+
var blueOffset = elemSize*i
|
|
285
|
+
SWEEP_EVENTS[ptr++] = blue[blueOffset+istart]
|
|
286
|
+
SWEEP_EVENTS[ptr++] = -idx
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
//process events from left->right
|
|
290
|
+
var n = ptr >>> 1
|
|
291
|
+
isort(SWEEP_EVENTS, n)
|
|
292
|
+
|
|
293
|
+
var redActive = 0
|
|
294
|
+
for(var i=0; i<n; ++i) {
|
|
295
|
+
var e = SWEEP_EVENTS[2*i+1]|0
|
|
296
|
+
if(e < 0) {
|
|
297
|
+
var idx = -e
|
|
298
|
+
var isRed = false
|
|
299
|
+
if(idx >= BLUE_FLAG) {
|
|
300
|
+
isRed = !flip
|
|
301
|
+
idx -= BLUE_FLAG
|
|
302
|
+
} else {
|
|
303
|
+
isRed = !!flip
|
|
304
|
+
idx -= 1
|
|
305
|
+
}
|
|
306
|
+
if(isRed) {
|
|
307
|
+
sqPush(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive++, idx)
|
|
308
|
+
} else {
|
|
309
|
+
var blueId = blueIndex[idx]
|
|
310
|
+
var bluePtr = elemSize * idx
|
|
311
|
+
|
|
312
|
+
var b0 = blue[bluePtr+axis+1]
|
|
313
|
+
var b1 = blue[bluePtr+axis+1+d]
|
|
314
|
+
|
|
315
|
+
red_loop:
|
|
316
|
+
for(var j=0; j<redActive; ++j) {
|
|
317
|
+
var oidx = RED_SWEEP_QUEUE[j]
|
|
318
|
+
var redPtr = elemSize * oidx
|
|
319
|
+
|
|
320
|
+
if(b1 < red[redPtr+axis+1] ||
|
|
321
|
+
red[redPtr+axis+1+d] < b0) {
|
|
322
|
+
continue
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
for(var k=axis+2; k<d; ++k) {
|
|
326
|
+
if(blue[bluePtr + k + d] < red[redPtr + k] ||
|
|
327
|
+
red[redPtr + k + d] < blue[bluePtr + k]) {
|
|
328
|
+
continue red_loop
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
var redId = redIndex[oidx]
|
|
333
|
+
var retval
|
|
334
|
+
if(flip) {
|
|
335
|
+
retval = visit(blueId, redId)
|
|
336
|
+
} else {
|
|
337
|
+
retval = visit(redId, blueId)
|
|
338
|
+
}
|
|
339
|
+
if(retval !== void 0) {
|
|
340
|
+
return retval
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
} else {
|
|
345
|
+
sqPop(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive--, e - redShift)
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function scanComplete(
|
|
351
|
+
d, axis, visit,
|
|
352
|
+
redStart, redEnd, red, redIndex,
|
|
353
|
+
blueStart, blueEnd, blue, blueIndex) {
|
|
354
|
+
|
|
355
|
+
var ptr = 0
|
|
356
|
+
var elemSize = 2*d
|
|
357
|
+
var istart = axis
|
|
358
|
+
var iend = axis+d
|
|
359
|
+
|
|
360
|
+
for(var i=redStart; i<redEnd; ++i) {
|
|
361
|
+
var idx = i + BLUE_FLAG
|
|
362
|
+
var redOffset = elemSize*i
|
|
363
|
+
SWEEP_EVENTS[ptr++] = red[redOffset+istart]
|
|
364
|
+
SWEEP_EVENTS[ptr++] = -idx
|
|
365
|
+
SWEEP_EVENTS[ptr++] = red[redOffset+iend]
|
|
366
|
+
SWEEP_EVENTS[ptr++] = idx
|
|
367
|
+
}
|
|
368
|
+
for(var i=blueStart; i<blueEnd; ++i) {
|
|
369
|
+
var idx = i + 1
|
|
370
|
+
var blueOffset = elemSize*i
|
|
371
|
+
SWEEP_EVENTS[ptr++] = blue[blueOffset+istart]
|
|
372
|
+
SWEEP_EVENTS[ptr++] = -idx
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
//process events from left->right
|
|
376
|
+
var n = ptr >>> 1
|
|
377
|
+
isort(SWEEP_EVENTS, n)
|
|
378
|
+
|
|
379
|
+
var redActive = 0
|
|
380
|
+
for(var i=0; i<n; ++i) {
|
|
381
|
+
var e = SWEEP_EVENTS[2*i+1]|0
|
|
382
|
+
if(e < 0) {
|
|
383
|
+
var idx = -e
|
|
384
|
+
if(idx >= BLUE_FLAG) {
|
|
385
|
+
RED_SWEEP_QUEUE[redActive++] = idx - BLUE_FLAG
|
|
386
|
+
} else {
|
|
387
|
+
idx -= 1
|
|
388
|
+
var blueId = blueIndex[idx]
|
|
389
|
+
var bluePtr = elemSize * idx
|
|
390
|
+
|
|
391
|
+
var b0 = blue[bluePtr+axis+1]
|
|
392
|
+
var b1 = blue[bluePtr+axis+1+d]
|
|
393
|
+
|
|
394
|
+
red_loop:
|
|
395
|
+
for(var j=0; j<redActive; ++j) {
|
|
396
|
+
var oidx = RED_SWEEP_QUEUE[j]
|
|
397
|
+
var redId = redIndex[oidx]
|
|
398
|
+
|
|
399
|
+
if(redId === blueId) {
|
|
400
|
+
break
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
var redPtr = elemSize * oidx
|
|
404
|
+
if(b1 < red[redPtr+axis+1] ||
|
|
405
|
+
red[redPtr+axis+1+d] < b0) {
|
|
406
|
+
continue
|
|
407
|
+
}
|
|
408
|
+
for(var k=axis+2; k<d; ++k) {
|
|
409
|
+
if(blue[bluePtr + k + d] < red[redPtr + k] ||
|
|
410
|
+
red[redPtr + k + d] < blue[bluePtr + k]) {
|
|
411
|
+
continue red_loop
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
var retval = visit(redId, blueId)
|
|
416
|
+
if(retval !== void 0) {
|
|
417
|
+
return retval
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
} else {
|
|
422
|
+
var idx = e - BLUE_FLAG
|
|
423
|
+
for(var j=redActive-1; j>=0; --j) {
|
|
424
|
+
if(RED_SWEEP_QUEUE[j] === idx) {
|
|
425
|
+
for(var k=j+1; k<redActive; ++k) {
|
|
426
|
+
RED_SWEEP_QUEUE[k-1] = RED_SWEEP_QUEUE[k]
|
|
427
|
+
}
|
|
428
|
+
break
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
--redActive
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "box-intersect",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"author": "",
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"private": true,
|
|
9
|
+
"main": "index.js",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"array-shuffle": "^1.0.0",
|
|
15
|
+
"dup": "^1.0.0",
|
|
16
|
+
"guarded-array": "^1.0.0",
|
|
17
|
+
"iota-array": "^1.0.0",
|
|
18
|
+
"tape": "^5.9.0",
|
|
19
|
+
"uniq": "^1.0.1"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"bit-twiddle": "^1.0.2"
|
|
23
|
+
}
|
|
24
|
+
}
|