@dra2020/baseclient 1.0.12 → 1.0.13
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/package.json +16 -15
- package/LICENSE +0 -21
- package/README.md +0 -26
- package/dist/all/all.d.ts +0 -20
- package/dist/baseclient.js +0 -10113
- package/dist/baseclient.js.map +0 -1
- package/dist/context/all.d.ts +0 -1
- package/dist/context/context.d.ts +0 -13
- package/dist/filterexpr/all.d.ts +0 -1
- package/dist/filterexpr/filterexpr.d.ts +0 -67
- package/dist/fsm/all.d.ts +0 -1
- package/dist/fsm/fsm.d.ts +0 -119
- package/dist/geo/all.d.ts +0 -2
- package/dist/geo/geo.d.ts +0 -67
- package/dist/geo/vfeature.d.ts +0 -4
- package/dist/logabstract/all.d.ts +0 -1
- package/dist/logabstract/log.d.ts +0 -26
- package/dist/logclient/all.d.ts +0 -1
- package/dist/logclient/log.d.ts +0 -6
- package/dist/ot-editutil/all.d.ts +0 -2
- package/dist/ot-editutil/oteditutil.d.ts +0 -14
- package/dist/ot-editutil/otmaputil.d.ts +0 -21
- package/dist/ot-js/all.d.ts +0 -9
- package/dist/ot-js/otarray.d.ts +0 -111
- package/dist/ot-js/otclientengine.d.ts +0 -38
- package/dist/ot-js/otcomposite.d.ts +0 -37
- package/dist/ot-js/otcounter.d.ts +0 -17
- package/dist/ot-js/otengine.d.ts +0 -22
- package/dist/ot-js/otmap.d.ts +0 -19
- package/dist/ot-js/otserverengine.d.ts +0 -38
- package/dist/ot-js/otsession.d.ts +0 -114
- package/dist/ot-js/ottypes.d.ts +0 -29
- package/dist/poly/all.d.ts +0 -15
- package/dist/poly/blend.d.ts +0 -1
- package/dist/poly/boundbox.d.ts +0 -16
- package/dist/poly/cartesian.d.ts +0 -5
- package/dist/poly/graham-scan.d.ts +0 -8
- package/dist/poly/hash.d.ts +0 -1
- package/dist/poly/matrix.d.ts +0 -24
- package/dist/poly/minbound.d.ts +0 -1
- package/dist/poly/poly.d.ts +0 -52
- package/dist/poly/polybin.d.ts +0 -5
- package/dist/poly/polylabel.d.ts +0 -7
- package/dist/poly/polypack.d.ts +0 -30
- package/dist/poly/polyround.d.ts +0 -1
- package/dist/poly/polysimplify.d.ts +0 -1
- package/dist/poly/quad.d.ts +0 -48
- package/dist/poly/selfintersect.d.ts +0 -1
- package/dist/poly/shamos.d.ts +0 -1
- package/dist/poly/simplify.d.ts +0 -2
- package/dist/poly/topo.d.ts +0 -46
- package/dist/poly/union.d.ts +0 -49
- package/dist/util/all.d.ts +0 -5
- package/dist/util/bintrie.d.ts +0 -93
- package/dist/util/countedhash.d.ts +0 -19
- package/dist/util/gradient.d.ts +0 -15
- package/dist/util/indexedarray.d.ts +0 -15
- package/dist/util/util.d.ts +0 -68
- package/docs/context.md +0 -2
- package/docs/filterexpr.md +0 -22
- package/docs/fsm.md +0 -243
- package/docs/logabstract.md +0 -2
- package/docs/logclient.md +0 -2
- package/docs/ot-editutil.md +0 -2
- package/docs/ot-js.md +0 -95
- package/docs/poly.md +0 -103
- package/docs/util.md +0 -2
- package/lib/all/all.ts +0 -21
- package/lib/context/all.ts +0 -1
- package/lib/context/context.ts +0 -82
- package/lib/filterexpr/all.ts +0 -1
- package/lib/filterexpr/filterexpr.ts +0 -699
- package/lib/fsm/all.ts +0 -1
- package/lib/fsm/fsm.ts +0 -559
- package/lib/geo/all.ts +0 -2
- package/lib/geo/geo.ts +0 -452
- package/lib/geo/vfeature.ts +0 -34
- package/lib/logabstract/all.ts +0 -1
- package/lib/logabstract/log.ts +0 -55
- package/lib/logclient/all.ts +0 -1
- package/lib/logclient/log.ts +0 -105
- package/lib/ot-editutil/all.ts +0 -2
- package/lib/ot-editutil/oteditutil.ts +0 -180
- package/lib/ot-editutil/otmaputil.ts +0 -209
- package/lib/ot-js/all.ts +0 -9
- package/lib/ot-js/otarray.ts +0 -1168
- package/lib/ot-js/otclientengine.ts +0 -327
- package/lib/ot-js/otcomposite.ts +0 -247
- package/lib/ot-js/otcounter.ts +0 -145
- package/lib/ot-js/otengine.ts +0 -71
- package/lib/ot-js/otmap.ts +0 -144
- package/lib/ot-js/otserverengine.ts +0 -329
- package/lib/ot-js/otsession.ts +0 -202
- package/lib/ot-js/ottypes.ts +0 -98
- package/lib/poly/all.ts +0 -15
- package/lib/poly/blend.ts +0 -27
- package/lib/poly/boundbox.ts +0 -102
- package/lib/poly/cartesian.ts +0 -130
- package/lib/poly/graham-scan.ts +0 -401
- package/lib/poly/hash.ts +0 -15
- package/lib/poly/matrix.ts +0 -309
- package/lib/poly/minbound.ts +0 -211
- package/lib/poly/poly.ts +0 -767
- package/lib/poly/polybin.ts +0 -218
- package/lib/poly/polylabel.ts +0 -204
- package/lib/poly/polypack.ts +0 -468
- package/lib/poly/polyround.ts +0 -30
- package/lib/poly/polysimplify.ts +0 -24
- package/lib/poly/quad.ts +0 -272
- package/lib/poly/selfintersect.ts +0 -87
- package/lib/poly/shamos.ts +0 -297
- package/lib/poly/simplify.ts +0 -119
- package/lib/poly/topo.ts +0 -499
- package/lib/poly/union.ts +0 -388
- package/lib/util/all.ts +0 -5
- package/lib/util/bintrie.ts +0 -603
- package/lib/util/countedhash.ts +0 -83
- package/lib/util/gradient.ts +0 -108
- package/lib/util/indexedarray.ts +0 -80
- package/lib/util/util.ts +0 -695
package/lib/poly/polybin.ts
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
import * as Util from '../util/all';
|
|
2
|
-
import * as PP from './polypack';
|
|
3
|
-
import * as T from './topo';
|
|
4
|
-
|
|
5
|
-
// Packed Buffer format:
|
|
6
|
-
//
|
|
7
|
-
// (strings are packed as UTF8 bytes, padded to 4 byte boundary)
|
|
8
|
-
//
|
|
9
|
-
// { 4 byte size (byte offset to packed coordinate buffer) }
|
|
10
|
-
// { 4 byte length: property name,
|
|
11
|
-
// 4 byte length: json string }*
|
|
12
|
-
// { 4 byte length: 'features' }
|
|
13
|
-
// { 4 byte length: length of 'features' array }
|
|
14
|
-
// { 4 byte length: property name,
|
|
15
|
-
// 4 byte length: json string }*
|
|
16
|
-
// { padding to 8 byte boundary }
|
|
17
|
-
// { packed buffer coordinates in polypack format (indexed by geometry.packed above) }
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
const MagicInt = 17;
|
|
21
|
-
const MagicFloat = 17.17;
|
|
22
|
-
|
|
23
|
-
function pad(n: number, pad: number): number
|
|
24
|
-
{
|
|
25
|
-
let mod = n % pad;
|
|
26
|
-
return mod ? pad - mod : 0;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function sizeOfString(coder: Util.Coder, s: string): number
|
|
30
|
-
{
|
|
31
|
-
let s8 = Util.s2u8(coder, s);
|
|
32
|
-
return 4 + s8.length + pad(s8.length, 4);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function packString(coder: Util.Coder, buf8: Uint8Array, buf32: Int32Array, offset: number, s: string): number
|
|
36
|
-
{
|
|
37
|
-
let s8 = Util.s2u8(coder, s);
|
|
38
|
-
buf32[offset >> 2] = s8.length;
|
|
39
|
-
offset += 4;
|
|
40
|
-
let i: number;
|
|
41
|
-
for (i = 0; i < s8.length; i++) buf8[offset++] = s8[i];
|
|
42
|
-
offset += pad(offset, 4);
|
|
43
|
-
return offset;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function unpackString(coder: Util.Coder, buf8: Uint8Array, buf32: Int32Array, offset: number): string
|
|
47
|
-
{
|
|
48
|
-
let size = buf32[offset >> 2];
|
|
49
|
-
let s = Util.u82s(coder, buf8, offset+4, size);
|
|
50
|
-
return s;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function packCollection(coder: Util.Coder, col: any): ArrayBuffer
|
|
54
|
-
{
|
|
55
|
-
// Compute size
|
|
56
|
-
let pp = PP.featurePack(col) as PP.PolyPack;
|
|
57
|
-
let buffer: any = col.features.length ? col.features[0].geometry.packed.buffer : null; // to restore, below
|
|
58
|
-
let size = 16; // int endiness, offset to coordinates, float endiness
|
|
59
|
-
col.features.forEach((f: any) => { delete f.geometry.packed.buffer; }); // reconstructed when unpacking
|
|
60
|
-
let j = JSON.stringify(col);
|
|
61
|
-
size += sizeOfString(coder, j);
|
|
62
|
-
size += pad(size, 8);
|
|
63
|
-
let fullsize = size + pp.length * 8; // add space for coordinates
|
|
64
|
-
|
|
65
|
-
// Now pack it
|
|
66
|
-
let ab = new ArrayBuffer(fullsize);
|
|
67
|
-
let buf8 = new Uint8Array(ab);
|
|
68
|
-
let buf32 = new Int32Array(ab);
|
|
69
|
-
let buf64 = new Float64Array(ab);
|
|
70
|
-
let offset = 0;
|
|
71
|
-
buf32[0] = MagicInt;
|
|
72
|
-
offset += 4;
|
|
73
|
-
buf32[1] = size;
|
|
74
|
-
offset += 4;
|
|
75
|
-
buf64[1] = MagicFloat; // Note that buf64[0] has the two ints stored above
|
|
76
|
-
offset += 8;
|
|
77
|
-
offset = packString(coder, buf8, buf32, offset, j);
|
|
78
|
-
offset += pad(offset, 8);
|
|
79
|
-
if (offset != size)
|
|
80
|
-
throw 'Oops, packing error.';
|
|
81
|
-
let foff = offset >> 3;
|
|
82
|
-
let buf = pp.buffer as Float64Array;
|
|
83
|
-
for (let i: number = 0; i < pp.length; i++)
|
|
84
|
-
buf64[foff++] = buf[i];
|
|
85
|
-
|
|
86
|
-
// Now restore
|
|
87
|
-
col.features.forEach((f: any) => { f.geometry.packed.buffer = buffer; });
|
|
88
|
-
PP.featureUnpack(col);
|
|
89
|
-
|
|
90
|
-
return ab;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function reverse(buf8: Uint8Array, s: number, n: number): void
|
|
94
|
-
{
|
|
95
|
-
let e = s + n - 1;
|
|
96
|
-
while (s < e)
|
|
97
|
-
{
|
|
98
|
-
let t = buf8[s];
|
|
99
|
-
buf8[s] = buf8[e];
|
|
100
|
-
buf8[e] = t;
|
|
101
|
-
s++, e--;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function enforceEndianness(ab: ArrayBuffer): void
|
|
106
|
-
{
|
|
107
|
-
let buf8 = new Uint8Array(ab);
|
|
108
|
-
let buf32 = new Int32Array(ab);
|
|
109
|
-
let buf64 = new Float64Array(ab);
|
|
110
|
-
let reverseInts = false;
|
|
111
|
-
if (buf32[0] != MagicInt)
|
|
112
|
-
{
|
|
113
|
-
reverseInts = true;
|
|
114
|
-
reverse(buf8, 0, 4);
|
|
115
|
-
if (buf32[0] != MagicInt) throw 'unpackCollection: badly formatted buffer';
|
|
116
|
-
reverse(buf8, 4, 4); // size of non-floats
|
|
117
|
-
}
|
|
118
|
-
let reverseFloats = false;
|
|
119
|
-
if (buf64[1] != MagicFloat)
|
|
120
|
-
{
|
|
121
|
-
reverseFloats = true;
|
|
122
|
-
reverse(buf8, 8, 8);
|
|
123
|
-
if (buf64[1] != MagicFloat) throw 'unpackCollection: badly formatted buffer';
|
|
124
|
-
}
|
|
125
|
-
if (reverseInts)
|
|
126
|
-
reverse(buf8, 16, 4); // JSON string length
|
|
127
|
-
if (reverseFloats)
|
|
128
|
-
{
|
|
129
|
-
let s = buf32[1]; // Offset to floats
|
|
130
|
-
let e = ab.byteLength;
|
|
131
|
-
for (; s < e; s += 8)
|
|
132
|
-
reverse(buf8, s, 8);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export function unpackCollection(coder: Util.Coder, ab: ArrayBuffer): any
|
|
137
|
-
{
|
|
138
|
-
enforceEndianness(ab);
|
|
139
|
-
let col: any = {};
|
|
140
|
-
let buf8 = new Uint8Array(ab);
|
|
141
|
-
let buf32 = new Int32Array(ab);
|
|
142
|
-
let size = buf32[1];
|
|
143
|
-
let buf64 = new Float64Array(ab, size); // offset to start of packed coordinates
|
|
144
|
-
let offset = 16;
|
|
145
|
-
let j = unpackString(coder, buf8, buf32, offset);
|
|
146
|
-
col = JSON.parse(j);
|
|
147
|
-
col.features.forEach((f: any) => { f.geometry.packed.buffer = buf64 });
|
|
148
|
-
return col;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Format of packed buffer:
|
|
152
|
-
// [Size of JSON string] [4 bytes]
|
|
153
|
-
// [Size of packedarcs] [4 bytes]
|
|
154
|
-
// [Size of packedarcindices] [4 bytes]
|
|
155
|
-
// [padding] [4 bytes]
|
|
156
|
-
// [JSON string]
|
|
157
|
-
// [pad to 8]
|
|
158
|
-
// [packedarcs]
|
|
159
|
-
// [packedarcindices]
|
|
160
|
-
|
|
161
|
-
const HeaderSize = 16; // 4 Int32's
|
|
162
|
-
|
|
163
|
-
export function topoToBuffer(coder: Util.Coder, topo: any): ArrayBuffer
|
|
164
|
-
{
|
|
165
|
-
// Make sure we're packed
|
|
166
|
-
T.topoPack(topo);
|
|
167
|
-
let savepack = topo.packed;
|
|
168
|
-
delete topo.packed;
|
|
169
|
-
let json = JSON.stringify(topo);
|
|
170
|
-
let byteLength = HeaderSize; // 3 lengths + padding
|
|
171
|
-
let stringLength = sizeOfString(coder, json);
|
|
172
|
-
stringLength += pad(stringLength, 8);
|
|
173
|
-
byteLength += stringLength;
|
|
174
|
-
byteLength += savepack.arcs.byteLength;
|
|
175
|
-
byteLength += savepack.arcindices.byteLength;
|
|
176
|
-
let ab = new ArrayBuffer(byteLength);
|
|
177
|
-
let buf8 = new Uint8Array(ab);
|
|
178
|
-
let buf32 = new Int32Array(ab);
|
|
179
|
-
let buf64 = new Float64Array(ab, HeaderSize + stringLength, savepack.arcs.length);
|
|
180
|
-
|
|
181
|
-
buf32[0] = stringLength;
|
|
182
|
-
buf32[1] = savepack.arcs.byteLength;
|
|
183
|
-
buf32[2] = savepack.arcindices.byteLength;
|
|
184
|
-
buf32[3] = 0;
|
|
185
|
-
packString(coder, buf8, buf32, HeaderSize, json); json = null;
|
|
186
|
-
let af = savepack.arcs as Float64Array;
|
|
187
|
-
let n = af.length;
|
|
188
|
-
let i = 0;
|
|
189
|
-
let j = 0;
|
|
190
|
-
while (i < n)
|
|
191
|
-
buf64[j++] = af[i++];
|
|
192
|
-
let ai = savepack.arcindices as Int32Array;
|
|
193
|
-
n = ai.length;
|
|
194
|
-
i = 0;
|
|
195
|
-
j = (HeaderSize + stringLength + savepack.arcs.byteLength) / 4;
|
|
196
|
-
while (i < n)
|
|
197
|
-
buf32[j++] = ai[i++];
|
|
198
|
-
|
|
199
|
-
// restore
|
|
200
|
-
topo.packed = savepack;
|
|
201
|
-
|
|
202
|
-
return ab;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export function topoFromBuffer(coder: Util.Coder, ab: ArrayBuffer): any
|
|
206
|
-
{
|
|
207
|
-
let buf8 = new Uint8Array(ab);
|
|
208
|
-
let buf32 = new Int32Array(ab);
|
|
209
|
-
let stringLength = buf32[0];
|
|
210
|
-
let arcsByteLength = buf32[1];
|
|
211
|
-
let arcindicesByteLength = buf32[2];
|
|
212
|
-
let json = unpackString(coder, buf8, buf32, HeaderSize);
|
|
213
|
-
let topo = JSON.parse(json);
|
|
214
|
-
topo.packed = {};
|
|
215
|
-
topo.packed.arcs = new Float64Array(ab, stringLength + HeaderSize, arcsByteLength / 8);
|
|
216
|
-
topo.packed.arcindices = new Int32Array(ab, stringLength + HeaderSize + arcsByteLength, arcindicesByteLength / 4);
|
|
217
|
-
return topo;
|
|
218
|
-
}
|
package/lib/poly/polylabel.ts
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import TinyQueue from 'tinyqueue';
|
|
2
|
-
import * as Util from '../util/all';
|
|
3
|
-
import * as P from './poly';
|
|
4
|
-
import * as PP from './polypack';
|
|
5
|
-
import * as BB from './boundbox';
|
|
6
|
-
|
|
7
|
-
interface PolyLabelResult
|
|
8
|
-
{
|
|
9
|
-
x: number;
|
|
10
|
-
y: number;
|
|
11
|
-
d: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
//
|
|
15
|
-
// polyLabel: given polygon, return contained point furthest from any edge, and that distance
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
export function polyLabel(poly: any, precision?: number, debug?: boolean): PolyLabelResult
|
|
19
|
-
{
|
|
20
|
-
let pp = P.polyNormalize(poly);
|
|
21
|
-
if (pp == null) return { x: 0, y: 0, d: 0 };
|
|
22
|
-
|
|
23
|
-
// For multi-polygon, pick largest polygon
|
|
24
|
-
let iLargest: number;
|
|
25
|
-
let nLargestArea: number;
|
|
26
|
-
PP.polyPackEachRing(pp, (b: Float64Array, iPoly: number, iRing: number, iOffset: number, nPoints: number) => {
|
|
27
|
-
if (iRing) return;
|
|
28
|
-
let nArea = P.polySimpleArea(b, iOffset, nPoints);
|
|
29
|
-
if (iLargest === undefined || nArea > nLargestArea) { iLargest = iPoly, nLargestArea = nArea }
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
if (iLargest === undefined)
|
|
33
|
-
return { x: 0, y: 0, d: 0 };
|
|
34
|
-
|
|
35
|
-
precision = precision || 0.00001;
|
|
36
|
-
|
|
37
|
-
let forEachPoint = (iter: any) => {
|
|
38
|
-
PP.polyPackEachPoint(pp, (b: Float64Array, iPoly: number, iRing: number, iOffset: number) => {
|
|
39
|
-
if (iPoly != iLargest || iRing) return;
|
|
40
|
-
iter(b[iOffset], b[iOffset+1]);
|
|
41
|
-
});
|
|
42
|
-
};
|
|
43
|
-
let forEachPointPair = (iter: any) => {
|
|
44
|
-
PP.polyPackEachRing(pp, (b: Float64Array, iPoly, iRing: number, iOffset: number, nPoints: number) => {
|
|
45
|
-
if (iPoly != iLargest || iRing) return;
|
|
46
|
-
let iFirst = iOffset;
|
|
47
|
-
let iLast = iOffset + nPoints * 2;
|
|
48
|
-
let iSecond = iLast - 2;
|
|
49
|
-
for (; iFirst < iLast; iSecond = iFirst, iFirst += 2)
|
|
50
|
-
iter(b[iFirst], b[iFirst+1], b[iSecond], b[iSecond+1]);
|
|
51
|
-
});
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
// find the bounding box of the outer ring
|
|
55
|
-
let minX: number, minY: number, maxX: number, maxY: number;
|
|
56
|
-
forEachPoint((x: number, y: number) => {
|
|
57
|
-
if (minX === undefined || x < minX) minX = x;
|
|
58
|
-
if (minY === undefined || y < minY) minY = y;
|
|
59
|
-
if (maxX === undefined || x > maxX) maxX = x;
|
|
60
|
-
if (maxY === undefined || y > maxY) maxY = y;
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
let width: number = maxX - minX;
|
|
64
|
-
let height: number = maxY - minY;
|
|
65
|
-
let cellSize: number = Math.min(width, height);
|
|
66
|
-
let h: number = cellSize / 2;
|
|
67
|
-
|
|
68
|
-
if (cellSize === 0) return { x: minX, y: minY, d: 0 };
|
|
69
|
-
|
|
70
|
-
// a priority queue of cells in order of their "potential" (max distance to polygon)
|
|
71
|
-
let cellQueue = new TinyQueue<Cell>(undefined, compareMax);
|
|
72
|
-
|
|
73
|
-
// cover polygon with initial cells
|
|
74
|
-
for (let x: number = minX; x < maxX; x += cellSize)
|
|
75
|
-
{
|
|
76
|
-
for (let y: number = minY; y < maxY; y += cellSize)
|
|
77
|
-
cellQueue.push(new Cell(x + h, y + h, h, forEachPointPair));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// take centroid as the first best guess
|
|
81
|
-
let bestCell: any = getCentroidCell(forEachPointPair);
|
|
82
|
-
|
|
83
|
-
// special case for rectangular polygons
|
|
84
|
-
let bboxCell: Cell = new Cell(minX + width / 2, minY + height / 2, 0, forEachPointPair);
|
|
85
|
-
if (bboxCell.d > bestCell.d) bestCell = bboxCell;
|
|
86
|
-
|
|
87
|
-
let numProbes = cellQueue.length;
|
|
88
|
-
|
|
89
|
-
while (cellQueue.length)
|
|
90
|
-
{
|
|
91
|
-
// pick the most promising cell from the queue
|
|
92
|
-
let cell = cellQueue.pop();
|
|
93
|
-
|
|
94
|
-
// update the best cell if we found a better one
|
|
95
|
-
if (cell.d > bestCell.d)
|
|
96
|
-
{
|
|
97
|
-
bestCell = cell;
|
|
98
|
-
if (debug) console.log('found best %d after %d probes', Math.round(1e4 * cell.d) / 1e4, numProbes);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// do not drill down further if there's no chance of a better solution
|
|
102
|
-
if (cell.max - bestCell.d <= precision) continue;
|
|
103
|
-
|
|
104
|
-
// split the cell into four cells
|
|
105
|
-
h = cell.h / 2;
|
|
106
|
-
cellQueue.push(new Cell(cell.x - h, cell.y - h, h, forEachPointPair));
|
|
107
|
-
cellQueue.push(new Cell(cell.x + h, cell.y - h, h, forEachPointPair));
|
|
108
|
-
cellQueue.push(new Cell(cell.x - h, cell.y + h, h, forEachPointPair));
|
|
109
|
-
cellQueue.push(new Cell(cell.x + h, cell.y + h, h, forEachPointPair));
|
|
110
|
-
numProbes += 4;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (debug)
|
|
114
|
-
{
|
|
115
|
-
console.log('num probes: ' + numProbes);
|
|
116
|
-
console.log('best distance: ' + bestCell.d);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return { x: bestCell.x, y: bestCell.y, d: bestCell.d };
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function compareMax(a: Cell, b: Cell) { return b.max - a.max; }
|
|
123
|
-
|
|
124
|
-
class Cell
|
|
125
|
-
{
|
|
126
|
-
x: number;
|
|
127
|
-
y: number;
|
|
128
|
-
h: number;
|
|
129
|
-
d: number;
|
|
130
|
-
max: number;
|
|
131
|
-
|
|
132
|
-
constructor(x: number, y: number, h: number, forEachPointPair: any)
|
|
133
|
-
{
|
|
134
|
-
this.x = x; // cell center x
|
|
135
|
-
this.y = y; // cell center y
|
|
136
|
-
this.h = h; // half the cell size
|
|
137
|
-
this.d = pointToPolygonDist(x, y, forEachPointPair); // distance from cell center to polygon
|
|
138
|
-
this.max = this.d + this.h * Math.SQRT2; // max distance to polygon within a cell
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// signed distance from point to polygon outline (negative if point is outside)
|
|
143
|
-
function pointToPolygonDist(x: number, y: number, forEachPointPair: any): number
|
|
144
|
-
{
|
|
145
|
-
let inside: boolean = false;
|
|
146
|
-
let minDistSq: number = Infinity;
|
|
147
|
-
|
|
148
|
-
forEachPointPair((ax: number, ay: number, bx: number, by: number) => {
|
|
149
|
-
if ((ay > y !== by > y) && (x < (bx - ax) * (y - ay) / (by - ay) + ax))
|
|
150
|
-
inside = !inside;
|
|
151
|
-
|
|
152
|
-
minDistSq = Math.min(minDistSq, getSegDistSq(x, y, ax, ay, bx, by));
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
return (inside ? 1 : -1) * Math.sqrt(minDistSq);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// get polygon centroid
|
|
159
|
-
function getCentroidCell(forEachPointPair: any): Cell
|
|
160
|
-
{
|
|
161
|
-
let area = 0;
|
|
162
|
-
let x = 0;
|
|
163
|
-
let y = 0;
|
|
164
|
-
let fx: number;
|
|
165
|
-
let fy: number;
|
|
166
|
-
|
|
167
|
-
forEachPointPair((ax: number, ay: number, bx: number, by: number) => {
|
|
168
|
-
if (fx === undefined) fx = ax, fy = ay;
|
|
169
|
-
let f: number = ax * by - bx * ay;
|
|
170
|
-
x += (ax + bx) * f;
|
|
171
|
-
y += (ay + by) * f;
|
|
172
|
-
area += f * 3;
|
|
173
|
-
});
|
|
174
|
-
if (area === 0) return new Cell(fx, fy, 0, forEachPointPair);
|
|
175
|
-
return new Cell(x / area, y / area, 0, forEachPointPair);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// get squared distance from a point to a segment
|
|
179
|
-
function getSegDistSq(px: number, py: number, ax: number, ay: number, bx: number, by: number): number
|
|
180
|
-
{
|
|
181
|
-
let dx = bx - ax;
|
|
182
|
-
let dy = by - ay;
|
|
183
|
-
|
|
184
|
-
if (dx !== 0 || dy !== 0)
|
|
185
|
-
{
|
|
186
|
-
let t: number = ((px - ax) * dx + (py - ay) * dy) / (dx * dx + dy * dy);
|
|
187
|
-
|
|
188
|
-
if (t > 1)
|
|
189
|
-
{
|
|
190
|
-
ax = bx;
|
|
191
|
-
ay = by;
|
|
192
|
-
}
|
|
193
|
-
else if (t > 0)
|
|
194
|
-
{
|
|
195
|
-
ax += dx * t;
|
|
196
|
-
ay += dy * t;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
dx = px - ax;
|
|
201
|
-
dy = py - ay;
|
|
202
|
-
|
|
203
|
-
return dx * dx + dy * dy;
|
|
204
|
-
}
|