@dra2020/baseclient 1.0.13 → 1.0.14
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/LICENSE +21 -0
- package/README.md +37 -0
- package/dist/all/all.d.ts +36 -0
- package/dist/all/allclient.d.ts +18 -0
- package/dist/base.js +33010 -0
- package/dist/base.js.map +1 -0
- package/dist/baseclient.js +8991 -0
- package/dist/baseclient.js.map +1 -0
- package/dist/context/all.d.ts +1 -0
- package/dist/context/context.d.ts +13 -0
- package/dist/dbabstract/all.d.ts +1 -0
- package/dist/dbabstract/db.d.ts +83 -0
- package/dist/dbdynamo/all.d.ts +1 -0
- package/dist/dbdynamo/dbdynamo.d.ts +190 -0
- package/dist/filterexpr/all.d.ts +1 -0
- package/dist/filterexpr/filterexpr.d.ts +64 -0
- package/dist/fsm/all.d.ts +1 -0
- package/dist/fsm/fsm.d.ts +118 -0
- package/dist/fsmfile/all.d.ts +1 -0
- package/dist/fsmfile/fsmfile.d.ts +47 -0
- package/dist/jsonstream/all.d.ts +1 -0
- package/dist/jsonstream/jsonstream.d.ts +130 -0
- package/dist/lambda/all.d.ts +1 -0
- package/dist/lambda/env.d.ts +10 -0
- package/dist/lambda/lambda.d.ts +18 -0
- package/dist/logabstract/all.d.ts +1 -0
- package/dist/logabstract/log.d.ts +26 -0
- package/dist/logclient/all.d.ts +1 -0
- package/dist/logclient/log.d.ts +6 -0
- package/dist/logserver/all.d.ts +5 -0
- package/dist/logserver/log.d.ts +11 -0
- package/dist/logserver/logaccum.d.ts +154 -0
- package/dist/logserver/logblob.d.ts +24 -0
- package/dist/logserver/logconcat.d.ts +55 -0
- package/dist/logserver/logkey.d.ts +28 -0
- package/dist/memsqs/all.d.ts +4 -0
- package/dist/memsqs/client.d.ts +13 -0
- package/dist/memsqs/loopback.d.ts +11 -0
- package/dist/memsqs/orderedlist.d.ts +19 -0
- package/dist/memsqs/queue.d.ts +84 -0
- package/dist/memsqs/server.d.ts +37 -0
- package/dist/ot-editutil/all.d.ts +2 -0
- package/dist/ot-editutil/oteditutil.d.ts +14 -0
- package/dist/ot-editutil/otmaputil.d.ts +21 -0
- package/dist/ot-js/all.d.ts +9 -0
- package/dist/ot-js/otarray.d.ts +111 -0
- package/dist/ot-js/otclientengine.d.ts +38 -0
- package/dist/ot-js/otcomposite.d.ts +37 -0
- package/dist/ot-js/otcounter.d.ts +17 -0
- package/dist/ot-js/otengine.d.ts +22 -0
- package/dist/ot-js/otmap.d.ts +19 -0
- package/dist/ot-js/otserverengine.d.ts +38 -0
- package/dist/ot-js/otsession.d.ts +111 -0
- package/dist/ot-js/ottypes.d.ts +29 -0
- package/dist/poly/all.d.ts +15 -0
- package/dist/poly/blend.d.ts +1 -0
- package/dist/poly/boundbox.d.ts +16 -0
- package/dist/poly/cartesian.d.ts +5 -0
- package/dist/poly/graham-scan.d.ts +8 -0
- package/dist/poly/hash.d.ts +1 -0
- package/dist/poly/matrix.d.ts +24 -0
- package/dist/poly/minbound.d.ts +1 -0
- package/dist/poly/poly.d.ts +52 -0
- package/dist/poly/polybin.d.ts +5 -0
- package/dist/poly/polylabel.d.ts +7 -0
- package/dist/poly/polypack.d.ts +30 -0
- package/dist/poly/polyround.d.ts +1 -0
- package/dist/poly/polysimplify.d.ts +1 -0
- package/dist/poly/quad.d.ts +48 -0
- package/dist/poly/selfintersect.d.ts +1 -0
- package/dist/poly/shamos.d.ts +1 -0
- package/dist/poly/simplify.d.ts +2 -0
- package/dist/poly/topo.d.ts +46 -0
- package/dist/poly/union.d.ts +48 -0
- package/dist/storage/all.d.ts +4 -0
- package/dist/storage/datablob.d.ts +9 -0
- package/dist/storage/env.d.ts +10 -0
- package/dist/storage/splitsblob.d.ts +13 -0
- package/dist/storage/storage.d.ts +166 -0
- package/dist/storages3/all.d.ts +1 -0
- package/dist/storages3/s3.d.ts +62 -0
- package/dist/util/all.d.ts +5 -0
- package/dist/util/bintrie.d.ts +93 -0
- package/dist/util/countedhash.d.ts +19 -0
- package/dist/util/gradient.d.ts +15 -0
- package/dist/util/indexedarray.d.ts +15 -0
- package/dist/util/util.d.ts +68 -0
- package/docs/context.md +2 -0
- package/docs/dbabstract.md +2 -0
- package/docs/dbdynamo.md +2 -0
- package/docs/fsm.md +243 -0
- package/docs/fsmfile.md +2 -0
- package/docs/jsonstream.md +44 -0
- package/docs/lambda.md +2 -0
- package/docs/logabstract.md +2 -0
- package/docs/logclient.md +2 -0
- package/docs/logserver.md +2 -0
- package/docs/ot-editutil.md +2 -0
- package/docs/ot-js.md +95 -0
- package/docs/poly.md +103 -0
- package/docs/storage.md +2 -0
- package/docs/storages3.md +2 -0
- package/docs/util.md +2 -0
- package/lib/all/all.ts +41 -0
- package/lib/all/allclient.ts +19 -0
- package/lib/context/all.ts +1 -0
- package/lib/context/context.ts +82 -0
- package/lib/dbabstract/all.ts +1 -0
- package/lib/dbabstract/db.ts +246 -0
- package/lib/dbdynamo/all.ts +1 -0
- package/lib/dbdynamo/dbdynamo.ts +1551 -0
- package/lib/filterexpr/all.ts +1 -0
- package/lib/filterexpr/filterexpr.ts +625 -0
- package/lib/fsm/all.ts +1 -0
- package/lib/fsm/fsm.ts +549 -0
- package/lib/fsmfile/all.ts +1 -0
- package/lib/fsmfile/fsmfile.ts +236 -0
- package/lib/jsonstream/all.ts +1 -0
- package/lib/jsonstream/jsonstream.ts +940 -0
- package/lib/lambda/all.ts +1 -0
- package/lib/lambda/env.ts +13 -0
- package/lib/lambda/lambda.ts +120 -0
- package/lib/logabstract/all.ts +1 -0
- package/lib/logabstract/log.ts +55 -0
- package/lib/logclient/all.ts +1 -0
- package/lib/logclient/log.ts +105 -0
- package/lib/logserver/all.ts +5 -0
- package/lib/logserver/log.ts +565 -0
- package/lib/logserver/logaccum.ts +1445 -0
- package/lib/logserver/logblob.ts +84 -0
- package/lib/logserver/logconcat.ts +313 -0
- package/lib/logserver/logkey.ts +125 -0
- package/lib/memsqs/all.ts +4 -0
- package/lib/memsqs/client.ts +268 -0
- package/lib/memsqs/loopback.ts +64 -0
- package/lib/memsqs/orderedlist.ts +74 -0
- package/lib/memsqs/queue.ts +395 -0
- package/lib/memsqs/server.ts +262 -0
- package/lib/ot-editutil/all.ts +2 -0
- package/lib/ot-editutil/oteditutil.ts +180 -0
- package/lib/ot-editutil/otmaputil.ts +209 -0
- package/lib/ot-js/all.ts +9 -0
- package/lib/ot-js/otarray.ts +1168 -0
- package/lib/ot-js/otclientengine.ts +327 -0
- package/lib/ot-js/otcomposite.ts +247 -0
- package/lib/ot-js/otcounter.ts +145 -0
- package/lib/ot-js/otengine.ts +71 -0
- package/lib/ot-js/otmap.ts +144 -0
- package/lib/ot-js/otserverengine.ts +329 -0
- package/lib/ot-js/otsession.ts +199 -0
- package/lib/ot-js/ottypes.ts +98 -0
- package/lib/poly/all.ts +15 -0
- package/lib/poly/blend.ts +27 -0
- package/lib/poly/boundbox.ts +102 -0
- package/lib/poly/cartesian.ts +130 -0
- package/lib/poly/graham-scan.ts +401 -0
- package/lib/poly/hash.ts +15 -0
- package/lib/poly/matrix.ts +309 -0
- package/lib/poly/minbound.ts +211 -0
- package/lib/poly/poly.ts +767 -0
- package/lib/poly/polybin.ts +218 -0
- package/lib/poly/polylabel.ts +204 -0
- package/lib/poly/polypack.ts +458 -0
- package/lib/poly/polyround.ts +30 -0
- package/lib/poly/polysimplify.ts +24 -0
- package/lib/poly/quad.ts +272 -0
- package/lib/poly/selfintersect.ts +87 -0
- package/lib/poly/shamos.ts +297 -0
- package/lib/poly/simplify.ts +119 -0
- package/lib/poly/topo.ts +525 -0
- package/lib/poly/union.ts +371 -0
- package/lib/storage/all.ts +4 -0
- package/lib/storage/datablob.ts +36 -0
- package/lib/storage/env.ts +14 -0
- package/lib/storage/splitsblob.ts +63 -0
- package/lib/storage/storage.ts +604 -0
- package/lib/storages3/all.ts +1 -0
- package/lib/storages3/s3.ts +576 -0
- package/lib/util/all.ts +5 -0
- package/lib/util/bintrie.ts +603 -0
- package/lib/util/countedhash.ts +83 -0
- package/lib/util/gradient.ts +108 -0
- package/lib/util/indexedarray.ts +80 -0
- package/lib/util/util.ts +695 -0
- package/package.json +8 -8
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
//
|
|
2
|
+
// CONVEX HULL USING GRAHAM SCAN ALGORITHM
|
|
3
|
+
//
|
|
4
|
+
/* Resources:
|
|
5
|
+
* https://en.wikipedia.org/wiki/Graham_scan
|
|
6
|
+
* https://www.tutorialspoint.com/Graham-Scan-Algorithm <<< pseudo code
|
|
7
|
+
* http://brian3kb.github.io/graham_scan_js/ <<< basis for this implementation
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {polyNormalize, PolyOptions} from './poly';
|
|
11
|
+
import * as PP from './polypack';
|
|
12
|
+
|
|
13
|
+
type SimplePoint = [number, number];
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export function makeConvexHullGrahamScan(poly: any, options?: PolyOptions): any
|
|
17
|
+
{
|
|
18
|
+
let points = getExteriorPoints(poly);
|
|
19
|
+
if (points == null) return null;
|
|
20
|
+
|
|
21
|
+
let scanner = new GrahamScanner();
|
|
22
|
+
|
|
23
|
+
for (let pt of points) {
|
|
24
|
+
scanner.addPoint(pt);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const ch: SimplePoint[] = scanner.getHull();
|
|
28
|
+
|
|
29
|
+
return [ ch ];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// NOTE - This finds the exterior points of a polygon in standard form and returns
|
|
33
|
+
// it as an array if [x, y] points, in contrast to polyToExteriorPoints() which
|
|
34
|
+
// uses the packed format and the poly.ts-private point form.
|
|
35
|
+
function getExteriorPoints(poly: any): SimplePoint[]
|
|
36
|
+
{
|
|
37
|
+
let pp = polyNormalize(poly);
|
|
38
|
+
if (pp == null) return null;
|
|
39
|
+
|
|
40
|
+
let points: SimplePoint[] = [];
|
|
41
|
+
|
|
42
|
+
PP.polyPackEachPoint(pp, (b: Float64Array, iPoly: number, iRing: number, iOffset: number) => {
|
|
43
|
+
if (iRing > 0) return; // skip holes
|
|
44
|
+
points.push([b[iOffset], b[iOffset+1]]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return points.length > 0 ? points : null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const X = 0, Y = 1;
|
|
51
|
+
|
|
52
|
+
class GrahamScanner
|
|
53
|
+
{
|
|
54
|
+
anchorPoint: SimplePoint | undefined;
|
|
55
|
+
reverse: boolean;
|
|
56
|
+
points: SimplePoint[];
|
|
57
|
+
|
|
58
|
+
constructor()
|
|
59
|
+
{
|
|
60
|
+
this.anchorPoint = undefined;
|
|
61
|
+
this.reverse = false;
|
|
62
|
+
this.points = [];
|
|
63
|
+
}
|
|
64
|
+
_findPolarAngle(a: SimplePoint, b: SimplePoint): number
|
|
65
|
+
{
|
|
66
|
+
const ONE_RADIAN = 57.295779513082;
|
|
67
|
+
let deltaX, deltaY;
|
|
68
|
+
|
|
69
|
+
// If the points are undefined, return a zero difference angle.
|
|
70
|
+
if (!a || !b) return 0;
|
|
71
|
+
|
|
72
|
+
deltaX = (b[X] - a[X]);
|
|
73
|
+
deltaY = (b[Y] - a[Y]);
|
|
74
|
+
|
|
75
|
+
if (deltaX == 0 && deltaY == 0) {
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let angle = Math.atan2(deltaY, deltaX) * ONE_RADIAN;
|
|
80
|
+
|
|
81
|
+
if (this.reverse) {
|
|
82
|
+
if (angle <= 0) {
|
|
83
|
+
angle += 360;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else
|
|
87
|
+
{
|
|
88
|
+
if (angle >= 0) {
|
|
89
|
+
angle += 360;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return angle;
|
|
94
|
+
}
|
|
95
|
+
addPoint(pt: SimplePoint): void
|
|
96
|
+
{
|
|
97
|
+
// Check for a new anchor
|
|
98
|
+
const newAnchor =
|
|
99
|
+
( this.anchorPoint === undefined ) ||
|
|
100
|
+
( this.anchorPoint[Y] > pt[Y] ) ||
|
|
101
|
+
( this.anchorPoint[Y] === pt[Y] && this.anchorPoint[X] > pt[X] );
|
|
102
|
+
|
|
103
|
+
if ( newAnchor ) {
|
|
104
|
+
if ( this.anchorPoint !== undefined ) {
|
|
105
|
+
this.points.push(pt);
|
|
106
|
+
}
|
|
107
|
+
this.anchorPoint = pt;
|
|
108
|
+
}
|
|
109
|
+
else
|
|
110
|
+
{
|
|
111
|
+
this.points.push(pt);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
_sortPoints(): SimplePoint[]
|
|
115
|
+
{
|
|
116
|
+
var self = this;
|
|
117
|
+
|
|
118
|
+
return this.points.sort(function(a: SimplePoint, b: SimplePoint)
|
|
119
|
+
{
|
|
120
|
+
const polarA = self._findPolarAngle(self.anchorPoint as SimplePoint, a);
|
|
121
|
+
const polarB = self._findPolarAngle(self.anchorPoint as SimplePoint, b);
|
|
122
|
+
|
|
123
|
+
if (polarA < polarB) {
|
|
124
|
+
return -1;
|
|
125
|
+
}
|
|
126
|
+
if (polarA > polarB) {
|
|
127
|
+
return 1;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return 0;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
_checkPoints(p0: SimplePoint, p1: SimplePoint, p2: SimplePoint): boolean
|
|
134
|
+
{
|
|
135
|
+
let difAngle;
|
|
136
|
+
const cwAngle = this._findPolarAngle(p0, p1);
|
|
137
|
+
const ccwAngle = this._findPolarAngle(p0, p2);
|
|
138
|
+
|
|
139
|
+
if (cwAngle > ccwAngle) {
|
|
140
|
+
difAngle = cwAngle - ccwAngle;
|
|
141
|
+
|
|
142
|
+
return !(difAngle > 180);
|
|
143
|
+
}
|
|
144
|
+
else if (cwAngle < ccwAngle)
|
|
145
|
+
{
|
|
146
|
+
difAngle = ccwAngle - cwAngle;
|
|
147
|
+
|
|
148
|
+
return (difAngle > 180);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
getHull(): SimplePoint[]
|
|
154
|
+
{
|
|
155
|
+
let hullPoints: SimplePoint[] = [];
|
|
156
|
+
let points: SimplePoint[];
|
|
157
|
+
let pointsLength: number;
|
|
158
|
+
|
|
159
|
+
this.reverse = this.points.every(
|
|
160
|
+
function (point)
|
|
161
|
+
{
|
|
162
|
+
return (point[X] < 0 && point[Y] < 0);
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
points = this._sortPoints();
|
|
167
|
+
pointsLength = points.length;
|
|
168
|
+
|
|
169
|
+
// If there are less than 3 points, joining these points creates a correct hull.
|
|
170
|
+
if (pointsLength < 3) {
|
|
171
|
+
points.unshift(this.anchorPoint as SimplePoint);
|
|
172
|
+
return points;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Move first two points to output array
|
|
176
|
+
const first: SimplePoint = points.shift() as SimplePoint;
|
|
177
|
+
const second: SimplePoint = points.shift() as SimplePoint;
|
|
178
|
+
hullPoints.push(first, second);
|
|
179
|
+
|
|
180
|
+
// Scan is repeated until no concave points are present.
|
|
181
|
+
while (true) {
|
|
182
|
+
let p0: SimplePoint;
|
|
183
|
+
let p1: SimplePoint;
|
|
184
|
+
let p2: SimplePoint;
|
|
185
|
+
|
|
186
|
+
hullPoints.push(points.shift() as SimplePoint);
|
|
187
|
+
|
|
188
|
+
p0 = hullPoints[hullPoints.length - 3];
|
|
189
|
+
p1 = hullPoints[hullPoints.length - 2];
|
|
190
|
+
p2 = hullPoints[hullPoints.length - 1];
|
|
191
|
+
|
|
192
|
+
if (this._checkPoints(p0, p1, p2)) {
|
|
193
|
+
hullPoints.splice(hullPoints.length - 2, 1);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (points.length == 0)
|
|
197
|
+
{
|
|
198
|
+
if (pointsLength == hullPoints.length)
|
|
199
|
+
{
|
|
200
|
+
// Check for duplicate anchorPoint edge-case, if not found, add the anchorpoint as the first item.
|
|
201
|
+
const ap: SimplePoint = this.anchorPoint as SimplePoint;
|
|
202
|
+
// Remove any udefined elements in the hullPoints array.
|
|
203
|
+
hullPoints = hullPoints.filter(function(p) { return !!p; });
|
|
204
|
+
if (!hullPoints.some(function(p){
|
|
205
|
+
return(p[X] == ap[X] && p[Y] == ap[Y]);
|
|
206
|
+
})) {
|
|
207
|
+
hullPoints.unshift(this.anchorPoint as SimplePoint);
|
|
208
|
+
}
|
|
209
|
+
return hullPoints;
|
|
210
|
+
}
|
|
211
|
+
points = hullPoints;
|
|
212
|
+
pointsLength = points.length;
|
|
213
|
+
hullPoints = [];
|
|
214
|
+
const first: SimplePoint = points.shift() as SimplePoint;
|
|
215
|
+
const second: SimplePoint = points.shift() as SimplePoint;
|
|
216
|
+
hullPoints.push(first, second);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Graham's Scan Convex Hull Algorithm
|
|
224
|
+
* @desc An implementation of the Graham's Scan Convex Hull algorithm in JavaScript.
|
|
225
|
+
* @author Brian Barnett, brian@3kb.co.uk, http://brianbar.net/ || http://3kb.co.uk/
|
|
226
|
+
* @version 1.0.5
|
|
227
|
+
*/
|
|
228
|
+
|
|
229
|
+
/*
|
|
230
|
+
function ConvexHullGrahamScan() {
|
|
231
|
+
this.anchorPoint = undefined;
|
|
232
|
+
this.reverse = false;
|
|
233
|
+
this.points = [];
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
ConvexHullGrahamScan.prototype = {
|
|
237
|
+
|
|
238
|
+
constructor: ConvexHullGrahamScan,
|
|
239
|
+
|
|
240
|
+
Point: function (x, y) {
|
|
241
|
+
this.x = x;
|
|
242
|
+
this.y = y;
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
_findPolarAngle: function (a, b) {
|
|
246
|
+
var ONE_RADIAN = 57.295779513082;
|
|
247
|
+
var deltaX, deltaY;
|
|
248
|
+
|
|
249
|
+
//if the points are undefined, return a zero difference angle.
|
|
250
|
+
if (!a || !b) return 0;
|
|
251
|
+
|
|
252
|
+
deltaX = (b.x - a.x);
|
|
253
|
+
deltaY = (b.y - a.y);
|
|
254
|
+
|
|
255
|
+
if (deltaX == 0 && deltaY == 0) {
|
|
256
|
+
return 0;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
var angle = Math.atan2(deltaY, deltaX) * ONE_RADIAN;
|
|
260
|
+
|
|
261
|
+
if (this.reverse){
|
|
262
|
+
if (angle <= 0) {
|
|
263
|
+
angle += 360;
|
|
264
|
+
}
|
|
265
|
+
}else{
|
|
266
|
+
if (angle >= 0) {
|
|
267
|
+
angle += 360;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return angle;
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
addPoint: function (x, y) {
|
|
275
|
+
//Check for a new anchor
|
|
276
|
+
var newAnchor =
|
|
277
|
+
(this.anchorPoint === undefined) ||
|
|
278
|
+
( this.anchorPoint.y > y ) ||
|
|
279
|
+
( this.anchorPoint.y === y && this.anchorPoint.x > x );
|
|
280
|
+
|
|
281
|
+
if ( newAnchor ) {
|
|
282
|
+
if ( this.anchorPoint !== undefined ) {
|
|
283
|
+
this.points.push(new this.Point(this.anchorPoint.x, this.anchorPoint.y));
|
|
284
|
+
}
|
|
285
|
+
this.anchorPoint = new this.Point(x, y);
|
|
286
|
+
} else {
|
|
287
|
+
this.points.push(new this.Point(x, y));
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
|
|
291
|
+
_sortPoints: function () {
|
|
292
|
+
var self = this;
|
|
293
|
+
|
|
294
|
+
return this.points.sort(function (a, b) {
|
|
295
|
+
var polarA = self._findPolarAngle(self.anchorPoint, a);
|
|
296
|
+
var polarB = self._findPolarAngle(self.anchorPoint, b);
|
|
297
|
+
|
|
298
|
+
if (polarA < polarB) {
|
|
299
|
+
return -1;
|
|
300
|
+
}
|
|
301
|
+
if (polarA > polarB) {
|
|
302
|
+
return 1;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return 0;
|
|
306
|
+
});
|
|
307
|
+
},
|
|
308
|
+
|
|
309
|
+
_checkPoints: function (p0, p1, p2) {
|
|
310
|
+
var difAngle;
|
|
311
|
+
var cwAngle = this._findPolarAngle(p0, p1);
|
|
312
|
+
var ccwAngle = this._findPolarAngle(p0, p2);
|
|
313
|
+
|
|
314
|
+
if (cwAngle > ccwAngle) {
|
|
315
|
+
|
|
316
|
+
difAngle = cwAngle - ccwAngle;
|
|
317
|
+
|
|
318
|
+
return !(difAngle > 180);
|
|
319
|
+
|
|
320
|
+
} else if (cwAngle < ccwAngle) {
|
|
321
|
+
|
|
322
|
+
difAngle = ccwAngle - cwAngle;
|
|
323
|
+
|
|
324
|
+
return (difAngle > 180);
|
|
325
|
+
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return true;
|
|
329
|
+
},
|
|
330
|
+
|
|
331
|
+
getHull: function () {
|
|
332
|
+
var hullPoints = [],
|
|
333
|
+
points,
|
|
334
|
+
pointsLength;
|
|
335
|
+
|
|
336
|
+
this.reverse = this.points.every(function(point){
|
|
337
|
+
return (point.x < 0 && point.y < 0);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
points = this._sortPoints();
|
|
341
|
+
pointsLength = points.length;
|
|
342
|
+
|
|
343
|
+
//If there are less than 3 points, joining these points creates a correct hull.
|
|
344
|
+
if (pointsLength < 3) {
|
|
345
|
+
points.unshift(this.anchorPoint);
|
|
346
|
+
return points;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
//move first two points to output array
|
|
350
|
+
hullPoints.push(points.shift(), points.shift());
|
|
351
|
+
|
|
352
|
+
//scan is repeated until no concave points are present.
|
|
353
|
+
while (true) {
|
|
354
|
+
var p0,
|
|
355
|
+
p1,
|
|
356
|
+
p2;
|
|
357
|
+
|
|
358
|
+
hullPoints.push(points.shift());
|
|
359
|
+
|
|
360
|
+
p0 = hullPoints[hullPoints.length - 3];
|
|
361
|
+
p1 = hullPoints[hullPoints.length - 2];
|
|
362
|
+
p2 = hullPoints[hullPoints.length - 1];
|
|
363
|
+
|
|
364
|
+
if (this._checkPoints(p0, p1, p2)) {
|
|
365
|
+
hullPoints.splice(hullPoints.length - 2, 1);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (points.length == 0) {
|
|
369
|
+
if (pointsLength == hullPoints.length) {
|
|
370
|
+
//check for duplicate anchorPoint edge-case, if not found, add the anchorpoint as the first item.
|
|
371
|
+
var ap = this.anchorPoint;
|
|
372
|
+
//remove any udefined elements in the hullPoints array.
|
|
373
|
+
hullPoints = hullPoints.filter(function(p) { return !!p; });
|
|
374
|
+
if (!hullPoints.some(function(p){
|
|
375
|
+
return(p.x == ap.x && p.y == ap.y);
|
|
376
|
+
})) {
|
|
377
|
+
hullPoints.unshift(this.anchorPoint);
|
|
378
|
+
}
|
|
379
|
+
return hullPoints;
|
|
380
|
+
}
|
|
381
|
+
points = hullPoints;
|
|
382
|
+
pointsLength = points.length;
|
|
383
|
+
hullPoints = [];
|
|
384
|
+
hullPoints.push(points.shift(), points.shift());
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
// EXPORTS
|
|
391
|
+
|
|
392
|
+
if (typeof define === 'function' && define.amd) {
|
|
393
|
+
define(function() {
|
|
394
|
+
return ConvexHullGrahamScan;
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
if (typeof module !== 'undefined') {
|
|
398
|
+
module.exports = ConvexHullGrahamScan;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
*/
|
package/lib/poly/hash.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as objectHash from 'object-hash';
|
|
2
|
+
|
|
3
|
+
export function qhash(o: any, keys?: any): any
|
|
4
|
+
{
|
|
5
|
+
// Copy only specified keys into temp object if subset provided.
|
|
6
|
+
if (keys !== undefined)
|
|
7
|
+
{
|
|
8
|
+
let tmpO: any = {};
|
|
9
|
+
for (let p in keys) if (keys.hasOwnProperty(p))
|
|
10
|
+
tmpO[p] = o[p];
|
|
11
|
+
o = tmpO;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return objectHash(o, { unorderedArrays: true, unorderedSets: true, });
|
|
15
|
+
}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
//
|
|
2
|
+
// SOME BASIC MATRIX OPERATIONS FOR MBR
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
|
|
7
|
+
These custom functions are used by minimumBoundingRectangle(), instead of the
|
|
8
|
+
same-named mathjs versions. They are tailored specifically for that routine and
|
|
9
|
+
are NOT intended for general use.
|
|
10
|
+
|
|
11
|
+
export declare function matrix(x: Matrix): Matrix;
|
|
12
|
+
|
|
13
|
+
export declare function multiply(a: Matrix, b: Matrix): Matrix;
|
|
14
|
+
|
|
15
|
+
export declare function transpose(a: Matrix, b: Matrix): Matrix;
|
|
16
|
+
|
|
17
|
+
export declare function apply((a: Matrix, over: Dim, cb: applyCB): Vector;
|
|
18
|
+
|
|
19
|
+
export declare function min(a: Vector): number;
|
|
20
|
+
|
|
21
|
+
export declare function max(a: Vector): number;
|
|
22
|
+
|
|
23
|
+
export declare function concat(a: Matrix, b: Matrix, by: Dim): Matrix;
|
|
24
|
+
|
|
25
|
+
export declare function row(a: Matrix, i: number): Vector;
|
|
26
|
+
|
|
27
|
+
export declare function subtract(a: Vector, b: Vector): Vector;
|
|
28
|
+
|
|
29
|
+
export declare function dotMultiply(a: Vector, b: Vector): Vector;
|
|
30
|
+
|
|
31
|
+
export declare function index(a: Range, b: Range): Index;
|
|
32
|
+
|
|
33
|
+
export declare function range(start: number, end: number, includeEnd: boolean = false): Vector;
|
|
34
|
+
|
|
35
|
+
export declare function subset(a: Matrix, select: Index): Matrix;
|
|
36
|
+
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
export type Matrix = number[][];
|
|
41
|
+
export type Vector = number[]; // A general vector or a row or a column
|
|
42
|
+
export type Range = number[];
|
|
43
|
+
export type Index = number[][];
|
|
44
|
+
export type applyCB = (v: Vector) => number;
|
|
45
|
+
|
|
46
|
+
export const enum Dim
|
|
47
|
+
{
|
|
48
|
+
Rows,
|
|
49
|
+
Columns
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function matrix(a: Matrix): Matrix
|
|
53
|
+
{
|
|
54
|
+
return a;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function multiply(a: Matrix, b: Matrix): Matrix
|
|
58
|
+
{
|
|
59
|
+
protect((nRows(a) > 0), "In multiply, input matrix 'a' has no rows. ");
|
|
60
|
+
protect((nCols(a) > 0), "In multiply, input matrix 'a' has no columns. ");
|
|
61
|
+
protect((nRows(b) > 0), "In multiply, input matrix 'b' has no rows. ");
|
|
62
|
+
protect((nCols(b) > 0), "In multiply, input matrix 'b' has no columns. ");
|
|
63
|
+
|
|
64
|
+
const m = nRows(a);
|
|
65
|
+
const n = nCols(a);
|
|
66
|
+
const p = nRows(b);
|
|
67
|
+
const q = nCols(b);
|
|
68
|
+
|
|
69
|
+
protect((p == n), "In multiply, the # rows in matrix 'b' doesn't match the number of columns in matrix 'a'.");
|
|
70
|
+
|
|
71
|
+
let c: Matrix = initialize(m, n);
|
|
72
|
+
|
|
73
|
+
for (let i = 0; i < m; i++)
|
|
74
|
+
{
|
|
75
|
+
for (let j = 0; j < q; j++)
|
|
76
|
+
{
|
|
77
|
+
const aRow = row(a, i);
|
|
78
|
+
const bCol = column(b, j);
|
|
79
|
+
|
|
80
|
+
c[i][j] = dotProduct(aRow, bCol);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return c;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function transpose(a: Matrix): Matrix
|
|
88
|
+
{
|
|
89
|
+
protect((nRows(a) > 0), "In transpose, input matrix has no rows. ");
|
|
90
|
+
protect((nCols(a) > 0), "In transpose, input matrix has no columns. ");
|
|
91
|
+
|
|
92
|
+
const j = nRows(a);
|
|
93
|
+
const i = nCols(a);
|
|
94
|
+
|
|
95
|
+
let b: Matrix = initialize(i, j);
|
|
96
|
+
|
|
97
|
+
for (let m = 0; m < j; m++)
|
|
98
|
+
{
|
|
99
|
+
for (let n = 0; n < i; n++)
|
|
100
|
+
{
|
|
101
|
+
b[n][m] = a[m][n];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return b;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function apply(a: Matrix, over: Dim, cb: applyCB): Vector
|
|
109
|
+
{
|
|
110
|
+
protect((nRows(a) > 0), "In apply, input matrix has no rows. ");
|
|
111
|
+
protect((nCols(a) > 0), "In apply, input matrix has no columns. ");
|
|
112
|
+
|
|
113
|
+
let m = nRows(a);
|
|
114
|
+
let n = nCols(a);
|
|
115
|
+
|
|
116
|
+
let result: Vector = [];
|
|
117
|
+
|
|
118
|
+
const iEnd = (over == Dim.Rows) ? m : n;
|
|
119
|
+
const extractFn = (over == Dim.Rows) ? row : column;
|
|
120
|
+
|
|
121
|
+
for (let i = 0; i < iEnd; i++)
|
|
122
|
+
{
|
|
123
|
+
const v: Vector = extractFn(a, i);
|
|
124
|
+
result.push(cb(v));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function min(v: Vector): number
|
|
131
|
+
{
|
|
132
|
+
return Math.min(...v);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function max(v: Vector): number
|
|
136
|
+
{
|
|
137
|
+
return Math.max(...v);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function concat(a: Matrix, b: Matrix, by: Dim): Matrix
|
|
141
|
+
{
|
|
142
|
+
protect((nRows(a) > 0), "In concat, input matrix 'a' has no rows. ");
|
|
143
|
+
protect((nCols(a) > 0), "In concat, input matrix 'a' has no columns. ");
|
|
144
|
+
protect((nRows(b) > 0), "In concat, input matrix 'b' has no rows. ");
|
|
145
|
+
protect((nCols(b) > 0), "In concat, input matrix 'b' has no columns. ");
|
|
146
|
+
|
|
147
|
+
let m = nRows(a);
|
|
148
|
+
let n = nCols(a);
|
|
149
|
+
const p = nRows(b);
|
|
150
|
+
const q = nCols(b);
|
|
151
|
+
|
|
152
|
+
const {i, j} = (by == Dim.Columns) ? {i: m, j: n + q} : {i: m + p, j: n};
|
|
153
|
+
let c: Matrix = initialize(i, j);
|
|
154
|
+
|
|
155
|
+
if (by == Dim.Rows)
|
|
156
|
+
protect((n == q), "In concat, concatenating rows but the # of columns don't match. ");
|
|
157
|
+
else // (by == Dim.Columns)
|
|
158
|
+
protect((m == p), "In concat, concatenating columns but the # of rows don't match. ");
|
|
159
|
+
|
|
160
|
+
// Copy the first array
|
|
161
|
+
for (let i = 0; i < m; i++)
|
|
162
|
+
{
|
|
163
|
+
for (let j = 0; j < n; j++)
|
|
164
|
+
{
|
|
165
|
+
c[i][j] = a[i][j];
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
m = (by == Dim.Rows) ? m : 0;
|
|
170
|
+
n = (by == Dim.Columns) ? n : 0;
|
|
171
|
+
|
|
172
|
+
// Copy the second array to the right (by columns) or below (by rows)
|
|
173
|
+
for (let i = 0; i < p; i++)
|
|
174
|
+
{
|
|
175
|
+
for (let j = 0; j < q; j++)
|
|
176
|
+
{
|
|
177
|
+
c[i+m][j+n] = b[i][j];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return c;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function row(a: Matrix, i: number): Vector
|
|
185
|
+
{
|
|
186
|
+
protect((nRows(a) > 0), "In row, input matrix has no rows. ");
|
|
187
|
+
protect((nCols(a) > 0), "In row, input matrix has no columns. ");
|
|
188
|
+
protect((i >= 0), "In row, invalid row index.");
|
|
189
|
+
|
|
190
|
+
return a[i];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function column(a: Matrix, j: number): Vector
|
|
194
|
+
{
|
|
195
|
+
protect((nRows(a) > 0), "In column, input matrix has no rows. ");
|
|
196
|
+
protect((nCols(a) > 0), "In column, input matrix has no columns. ");
|
|
197
|
+
protect((j >= 0), "In row, invalid column index.");
|
|
198
|
+
|
|
199
|
+
let v: any = [];
|
|
200
|
+
|
|
201
|
+
for (let i = 0; i < nRows(a); i++)
|
|
202
|
+
{
|
|
203
|
+
v.push(a[i][j]);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return v;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function subtract(a: Vector, b: Vector): Vector
|
|
210
|
+
{
|
|
211
|
+
protect((a.length == b.length), "In subtract, the input vectors have different lengths.");
|
|
212
|
+
|
|
213
|
+
let c: Vector = [];
|
|
214
|
+
|
|
215
|
+
for (let i = 0; i < a.length; i++)
|
|
216
|
+
{
|
|
217
|
+
c.push(a[i] - b[i]);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return c;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function dotMultiply(a: Vector, b: Vector): Vector
|
|
224
|
+
{
|
|
225
|
+
protect((a.length > 0) && (a.length == b.length), "In dotMultiply, the vectors aren't the same length. ");
|
|
226
|
+
|
|
227
|
+
let c: Vector = [];
|
|
228
|
+
|
|
229
|
+
for (let i = 0; i < a.length; i++)
|
|
230
|
+
{
|
|
231
|
+
c.push(a[i] * b[i]);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return c;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function index(a: Range, b: Range): Index
|
|
238
|
+
{
|
|
239
|
+
return [a, b];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export function range(start: number, end: number, includeEnd: boolean = false): Vector
|
|
243
|
+
{
|
|
244
|
+
let r: Vector = [];
|
|
245
|
+
|
|
246
|
+
end += includeEnd ? 1 : 0;
|
|
247
|
+
for (let i = start; i < end; i++)
|
|
248
|
+
{
|
|
249
|
+
r.push(i);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return r;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export function subset(a: Matrix, select: Index): Matrix
|
|
256
|
+
{
|
|
257
|
+
protect((nRows(a) > 0), "In subset, input matrix has no rows. ");
|
|
258
|
+
protect((nCols(a) > 0), "In subset, input matrix has no columns. ");
|
|
259
|
+
|
|
260
|
+
protect((nRows(select) > 0), "In subset, input matrix has no rows. ");
|
|
261
|
+
protect((nCols(select) > 0), "In subset, input matrix has no columns. ");
|
|
262
|
+
|
|
263
|
+
const m = nRows(a);
|
|
264
|
+
const n = nCols(a);
|
|
265
|
+
|
|
266
|
+
const rowRange = row(select, 0) as Range;
|
|
267
|
+
const colRange = row(select, 1) as Range;
|
|
268
|
+
const p = rowRange.length;
|
|
269
|
+
const q = colRange.length;
|
|
270
|
+
|
|
271
|
+
let b: Matrix = initialize(p, q);
|
|
272
|
+
|
|
273
|
+
for (let i = 0; i < p; i++)
|
|
274
|
+
{
|
|
275
|
+
for (let j = 0; j < q; j++)
|
|
276
|
+
{
|
|
277
|
+
b[i][j] = a[rowRange[i]][colRange[j]];
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return b;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
// HELPERS
|
|
286
|
+
|
|
287
|
+
function initialize(rows: number, cols: number): Matrix
|
|
288
|
+
{
|
|
289
|
+
protect(((rows > 0) || (cols > 0)), "In initialize, the # of rows or columns is not positive. ");
|
|
290
|
+
|
|
291
|
+
return [...Array(rows)].fill(0).map(() => [...Array(cols)].fill(0));
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const nRows = (a: Matrix | Index) => a.length;
|
|
295
|
+
const nCols = (a: Matrix | Index) => (a.length > 0) ? a[0].length : 0;
|
|
296
|
+
|
|
297
|
+
export function dotProduct(a: Vector, b: Vector): number
|
|
298
|
+
{
|
|
299
|
+
protect((a.length > 0) && (a.length == b.length), "In dotProduct, the vectors aren't the same length. ");
|
|
300
|
+
|
|
301
|
+
return a.map((value, i) => value * b[i]).reduce((acc, val) => acc + val, 0);
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
function protect(condition: boolean, message: string): void
|
|
306
|
+
{
|
|
307
|
+
if (!condition)
|
|
308
|
+
throw new Error(message);
|
|
309
|
+
}
|