@vorplex/core 0.0.4 → 0.0.9
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/dist/consts/mime-type.const.d.ts +456 -0
- package/dist/consts/mime-type.const.js +456 -0
- package/dist/consts/unit.const.d.ts +22 -0
- package/dist/consts/unit.const.js +22 -0
- package/dist/functions/debounce.function.d.ts +1 -0
- package/dist/functions/debounce.function.js +12 -0
- package/dist/functions/is-node-environment.function.d.ts +1 -0
- package/dist/functions/is-node-environment.function.js +3 -0
- package/dist/functions/parse-path-selector.function.d.ts +2 -0
- package/dist/functions/parse-path-selector.function.js +17 -0
- package/dist/functions/parse-url.function.d.ts +12 -0
- package/dist/functions/parse-url.function.js +25 -0
- package/dist/index.d.ts +92 -0
- package/dist/index.js +93 -0
- package/dist/interfaces/group.interface.d.ts +4 -0
- package/dist/interfaces/group.interface.js +0 -0
- package/dist/interfaces/key-value.interface.d.ts +4 -0
- package/dist/interfaces/key-value.interface.js +0 -0
- package/dist/modules/api/socket.model.d.ts +26 -0
- package/dist/modules/api/socket.model.js +66 -0
- package/dist/modules/api/web-client.model.d.ts +16 -0
- package/dist/modules/api/web-client.model.js +34 -0
- package/dist/modules/array/array.util.d.ts +17 -0
- package/dist/modules/array/array.util.js +105 -0
- package/dist/modules/changes/changes.util.d.ts +45 -0
- package/dist/modules/changes/changes.util.js +330 -0
- package/dist/modules/color/color-data.interface.d.ts +10 -0
- package/dist/modules/color/color-data.interface.js +0 -0
- package/dist/modules/color/color-formats.const.d.ts +9 -0
- package/dist/modules/color/color-formats.const.js +8 -0
- package/dist/modules/color/color.type.d.ts +4 -0
- package/dist/modules/color/color.type.js +0 -0
- package/dist/modules/color/color.util.d.ts +41 -0
- package/dist/modules/color/color.util.js +327 -0
- package/dist/modules/color/colors.const.d.ts +151 -0
- package/dist/modules/color/colors.const.js +150 -0
- package/dist/modules/color/hsl.interface.d.ts +6 -0
- package/dist/modules/color/hsl.interface.js +0 -0
- package/dist/modules/color/hsv.interface.d.ts +6 -0
- package/dist/modules/color/hsv.interface.js +0 -0
- package/dist/modules/color/rgb.interface.d.ts +6 -0
- package/dist/modules/color/rgb.interface.js +0 -0
- package/dist/modules/compression/compression.util.d.ts +4 -0
- package/dist/modules/compression/compression.util.js +52 -0
- package/dist/modules/date/date.util.d.ts +37 -0
- package/dist/modules/date/date.util.js +84 -0
- package/dist/modules/enum/enum.util.d.ts +17 -0
- package/dist/modules/enum/enum.util.js +69 -0
- package/dist/modules/hash/hash.util.d.ts +3 -0
- package/dist/modules/hash/hash.util.js +9 -0
- package/dist/modules/id/id.util.d.ts +7 -0
- package/dist/modules/id/id.util.js +33 -0
- package/dist/modules/injector/decorators/inject-token.decorator.d.ts +14 -0
- package/dist/modules/injector/decorators/inject-token.decorator.js +12 -0
- package/dist/modules/injector/decorators/injectable.decorator.d.ts +9 -0
- package/dist/modules/injector/decorators/injectable.decorator.js +7 -0
- package/dist/modules/injector/injector.model.d.ts +25 -0
- package/dist/modules/injector/injector.model.js +152 -0
- package/dist/modules/injector/provider-scopes.enum.d.ts +5 -0
- package/dist/modules/injector/provider-scopes.enum.js +6 -0
- package/dist/modules/injector/provider.interface.d.ts +10 -0
- package/dist/modules/injector/provider.interface.js +0 -0
- package/dist/modules/json-filter/json-filter.function.d.ts +41 -0
- package/dist/modules/json-filter/json-filter.function.js +75 -0
- package/dist/modules/logging/console-logger.model.d.ts +36 -0
- package/dist/modules/logging/console-logger.model.js +44 -0
- package/dist/modules/logging/logger.model.d.ts +6 -0
- package/dist/modules/logging/logger.model.js +7 -0
- package/dist/modules/logging/task.d.ts +38 -0
- package/dist/modules/logging/task.js +133 -0
- package/dist/modules/math/line.d.ts +12 -0
- package/dist/modules/math/line.js +50 -0
- package/dist/modules/math/point.d.ts +34 -0
- package/dist/modules/math/point.js +71 -0
- package/dist/modules/math/polygon.d.ts +45 -0
- package/dist/modules/math/polygon.js +273 -0
- package/dist/modules/math/rect.d.ts +6 -0
- package/dist/modules/math/rect.js +0 -0
- package/dist/modules/math/size.d.ts +4 -0
- package/dist/modules/math/size.js +0 -0
- package/dist/modules/number/number.util.d.ts +9 -0
- package/dist/modules/number/number.util.js +27 -0
- package/dist/modules/object/object.util.d.ts +7 -0
- package/dist/modules/object/object.util.js +63 -0
- package/dist/modules/path/path.util.d.ts +11 -0
- package/dist/modules/path/path.util.js +59 -0
- package/dist/modules/random/random.util.d.ts +17 -0
- package/dist/modules/random/random.util.js +57 -0
- package/dist/modules/readable-stream/readable-stream.util.d.ts +3 -0
- package/dist/modules/readable-stream/readable-stream.util.js +26 -0
- package/dist/modules/reflection/interfaces/parameter.interface.d.ts +4 -0
- package/dist/modules/reflection/interfaces/parameter.interface.js +0 -0
- package/dist/modules/reflection/models/attribute.model.d.ts +12 -0
- package/dist/modules/reflection/models/attribute.model.js +17 -0
- package/dist/modules/reflection/models/class-attribute.model.d.ts +4 -0
- package/dist/modules/reflection/models/class-attribute.model.js +6 -0
- package/dist/modules/reflection/models/method-attribute.model.d.ts +5 -0
- package/dist/modules/reflection/models/method-attribute.model.js +8 -0
- package/dist/modules/reflection/models/parameter-attribute.model.d.ts +7 -0
- package/dist/modules/reflection/models/parameter-attribute.model.js +21 -0
- package/dist/modules/reflection/models/property-attribute.model.d.ts +5 -0
- package/dist/modules/reflection/models/property-attribute.model.js +8 -0
- package/dist/modules/reflection/models/property-proxy-attribute.model.d.ts +15 -0
- package/dist/modules/reflection/models/property-proxy-attribute.model.js +19 -0
- package/dist/modules/reflection/types/constructor.type.d.ts +2 -0
- package/dist/modules/reflection/types/constructor.type.js +0 -0
- package/dist/modules/reflection/types/instance.type.d.ts +7 -0
- package/dist/modules/reflection/types/instance.type.js +0 -0
- package/dist/modules/reflection/types/type.type.d.ts +2 -0
- package/dist/modules/reflection/types/type.type.js +0 -0
- package/dist/modules/reflection/utils/decorator.util.d.ts +70 -0
- package/dist/modules/reflection/utils/decorator.util.js +135 -0
- package/dist/modules/reflection/utils/reflection.util.d.ts +140 -0
- package/dist/modules/reflection/utils/reflection.util.js +311 -0
- package/dist/modules/router/router.util.d.ts +33 -0
- package/dist/modules/router/router.util.js +59 -0
- package/dist/modules/state/adaptors/array/array-adaptor.util.d.ts +25 -0
- package/dist/modules/state/adaptors/array/array-adaptor.util.js +97 -0
- package/dist/modules/state/adaptors/entity/entity-adaptor.util.d.ts +35 -0
- package/dist/modules/state/adaptors/entity/entity-adaptor.util.js +158 -0
- package/dist/modules/state/adaptors/entity/entity-map.type.d.ts +4 -0
- package/dist/modules/state/adaptors/entity/entity-map.type.js +0 -0
- package/dist/modules/state/adaptors/entity/entity.interface.d.ts +3 -0
- package/dist/modules/state/adaptors/entity/entity.interface.js +0 -0
- package/dist/modules/state/state.model.d.ts +46 -0
- package/dist/modules/state/state.model.js +129 -0
- package/dist/modules/state/update.type.d.ts +2 -0
- package/dist/modules/state/update.type.js +0 -0
- package/dist/modules/string/string.util.d.ts +11 -0
- package/dist/modules/string/string.util.js +42 -0
- package/dist/modules/subscribable/subscribable.model.d.ts +10 -0
- package/dist/modules/subscribable/subscribable.model.js +34 -0
- package/dist/modules/subscribable/subscription.interface.d.ts +3 -0
- package/dist/modules/subscribable/subscription.interface.js +0 -0
- package/dist/modules/tson/error.d.ts +8 -0
- package/dist/modules/tson/error.js +13 -0
- package/dist/modules/tson/schema.d.ts +10 -0
- package/dist/modules/tson/schema.js +0 -0
- package/dist/modules/tson/schemas/any.d.ts +14 -0
- package/dist/modules/tson/schemas/any.js +27 -0
- package/dist/modules/tson/schemas/array.d.ts +21 -0
- package/dist/modules/tson/schemas/array.js +80 -0
- package/dist/modules/tson/schemas/boolean.d.ts +14 -0
- package/dist/modules/tson/schemas/boolean.js +38 -0
- package/dist/modules/tson/schemas/enum.d.ts +15 -0
- package/dist/modules/tson/schemas/enum.js +43 -0
- package/dist/modules/tson/schemas/number.d.ts +20 -0
- package/dist/modules/tson/schemas/number.js +66 -0
- package/dist/modules/tson/schemas/object.d.ts +33 -0
- package/dist/modules/tson/schemas/object.js +88 -0
- package/dist/modules/tson/schemas/schema-base.d.ts +12 -0
- package/dist/modules/tson/schemas/schema-base.js +14 -0
- package/dist/modules/tson/schemas/string.d.ts +19 -0
- package/dist/modules/tson/schemas/string.js +60 -0
- package/dist/modules/tson/schemas/union.d.ts +16 -0
- package/dist/modules/tson/schemas/union.js +56 -0
- package/dist/modules/tson/tson.d.ts +41 -0
- package/dist/modules/tson/tson.js +138 -0
- package/dist/modules/tson/type.d.ts +53 -0
- package/dist/modules/tson/type.js +0 -0
- package/dist/modules/value/value.util.d.ts +18 -0
- package/dist/modules/value/value.util.js +180 -0
- package/dist/types/awaitable.type.d.ts +1 -0
- package/dist/types/awaitable.type.js +0 -0
- package/dist/types/camel-to-kebab.type.d.ts +1 -0
- package/dist/types/camel-to-kebab.type.js +0 -0
- package/dist/types/has-key.type.d.ts +3 -0
- package/dist/types/has-key.type.js +0 -0
- package/dist/types/is-union.type.d.ts +1 -0
- package/dist/types/is-union.type.js +0 -0
- package/dist/types/keys-of-type.type.d.ts +5 -0
- package/dist/types/keys-of-type.type.js +0 -0
- package/dist/types/keys-with-fix.type.d.ts +3 -0
- package/dist/types/keys-with-fix.type.js +0 -0
- package/dist/types/optional-keys.type.d.ts +6 -0
- package/dist/types/optional-keys.type.js +0 -0
- package/dist/types/partial.type.d.ts +6 -0
- package/dist/types/partial.type.js +0 -0
- package/dist/types/predicate.type.d.ts +1 -0
- package/dist/types/predicate.type.js +0 -0
- package/dist/types/recursive-readonly.type.d.ts +3 -0
- package/dist/types/recursive-readonly.type.js +0 -0
- package/dist/types/recursive-value.type.d.ts +3 -0
- package/dist/types/recursive-value.type.js +0 -0
- package/dist/types/selector.type.d.ts +1 -0
- package/dist/types/selector.type.js +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { $Value } from '../value/value.util';
|
|
2
|
+
import { Line } from './line';
|
|
3
|
+
import { $Point } from './point';
|
|
4
|
+
export class Polygon {
|
|
5
|
+
vertices;
|
|
6
|
+
constructor(vertices) {
|
|
7
|
+
this.vertices = vertices;
|
|
8
|
+
}
|
|
9
|
+
static getEdge(polygon, index) {
|
|
10
|
+
if (index < 0)
|
|
11
|
+
index += polygon.vertices.length;
|
|
12
|
+
return {
|
|
13
|
+
start: polygon.vertices[index],
|
|
14
|
+
end: polygon.vertices[index + 1] ?? polygon.vertices[0],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
getEdge(index) {
|
|
18
|
+
return Polygon.getEdge(this, index);
|
|
19
|
+
}
|
|
20
|
+
static getEdges(polygon) {
|
|
21
|
+
return polygon.vertices.map((vertex, index) => ({
|
|
22
|
+
start: vertex,
|
|
23
|
+
end: polygon.vertices[index === polygon.vertices.length - 1 ? 0 : index + 1],
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
getEdges() {
|
|
27
|
+
return Polygon.getEdges(this);
|
|
28
|
+
}
|
|
29
|
+
static containsPoint(polygon, point) {
|
|
30
|
+
const { x, y } = point;
|
|
31
|
+
let inside = false;
|
|
32
|
+
for (let i = 0, j = polygon.vertices.length - 1; i < polygon.vertices.length; j = i++) {
|
|
33
|
+
const xi = polygon.vertices[i].x, yi = polygon.vertices[i].y;
|
|
34
|
+
const xj = polygon.vertices[j].x, yj = polygon.vertices[j].y;
|
|
35
|
+
const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
|
|
36
|
+
if (intersect)
|
|
37
|
+
inside = !inside;
|
|
38
|
+
}
|
|
39
|
+
return inside;
|
|
40
|
+
}
|
|
41
|
+
containsPoint(point) {
|
|
42
|
+
return Polygon.containsPoint(this, point);
|
|
43
|
+
}
|
|
44
|
+
static move(polygon, position) {
|
|
45
|
+
const vertices = polygon.vertices.map((vertex) => $Point.plus(vertex, position));
|
|
46
|
+
return new Polygon(vertices);
|
|
47
|
+
}
|
|
48
|
+
move(position) {
|
|
49
|
+
return Polygon.move(this, position);
|
|
50
|
+
}
|
|
51
|
+
static getIntersections(a, b, unique) {
|
|
52
|
+
const intersections = {
|
|
53
|
+
intersections: [],
|
|
54
|
+
edges: {},
|
|
55
|
+
points: {},
|
|
56
|
+
};
|
|
57
|
+
for (let vertexIndexA = 0; vertexIndexA < a.vertices.length; vertexIndexA++) {
|
|
58
|
+
const edgeA = a.getEdge(vertexIndexA);
|
|
59
|
+
const startWithinB = b.containsPoint(edgeA.start);
|
|
60
|
+
const endWithinB = b.containsPoint(edgeA.end);
|
|
61
|
+
if (!startWithinB || !endWithinB) {
|
|
62
|
+
for (let vertexIndexB = 0; vertexIndexB < b.vertices.length; vertexIndexB++) {
|
|
63
|
+
const edgeB = b.getEdge(vertexIndexB);
|
|
64
|
+
const intersectionPoint = Line.getIntersect(edgeA, edgeB);
|
|
65
|
+
if (intersectionPoint) {
|
|
66
|
+
if (unique && intersections.points[intersectionPoint.toString()])
|
|
67
|
+
continue;
|
|
68
|
+
const intersection = {
|
|
69
|
+
polygonA: a,
|
|
70
|
+
polygonB: b,
|
|
71
|
+
edgeA,
|
|
72
|
+
edgeB,
|
|
73
|
+
edgeIndexA: vertexIndexA,
|
|
74
|
+
edgeIndexB: vertexIndexB,
|
|
75
|
+
point: intersectionPoint,
|
|
76
|
+
};
|
|
77
|
+
intersections.intersections.push(intersection);
|
|
78
|
+
intersections.edges[edgeA.toString()] = (intersections.edges[edgeA.toString()] ?? []).concat(intersection);
|
|
79
|
+
intersections.edges[edgeB.toString()] = (intersections.edges[edgeB.toString()] ?? []).concat(intersection);
|
|
80
|
+
intersections.points[intersectionPoint.toString()] = intersection;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return intersections;
|
|
86
|
+
}
|
|
87
|
+
getIntersections(polygon, unique) {
|
|
88
|
+
return Polygon.getIntersections(this, polygon, unique);
|
|
89
|
+
}
|
|
90
|
+
static getLineIntersections(polygon, line) {
|
|
91
|
+
const intersections = [];
|
|
92
|
+
for (let vertexIndex = 0; vertexIndex < polygon.vertices.length; vertexIndex++) {
|
|
93
|
+
const edge = Polygon.getEdge(polygon, vertexIndex);
|
|
94
|
+
const point = Line.getIntersect(edge, line);
|
|
95
|
+
if (point)
|
|
96
|
+
intersections.push({ edgeIndex: vertexIndex, edge, point });
|
|
97
|
+
}
|
|
98
|
+
return intersections;
|
|
99
|
+
}
|
|
100
|
+
getLineIntersections(polygon, line) {
|
|
101
|
+
return Polygon.getLineIntersections(polygon, line);
|
|
102
|
+
}
|
|
103
|
+
static subtract(a, b) {
|
|
104
|
+
const polygons = [];
|
|
105
|
+
const intersections = Polygon.getIntersections(a, b, true);
|
|
106
|
+
const visitedIntersections = {};
|
|
107
|
+
const trailA = (vertex, vertices = []) => {
|
|
108
|
+
if (typeof vertex === 'number' && vertex < 0)
|
|
109
|
+
vertex = a.vertices.length - 1;
|
|
110
|
+
if (vertex == null) {
|
|
111
|
+
if (Polygon.containsPoint(b, a.vertices[0])) {
|
|
112
|
+
return trailA(0, vertices);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
vertices.push(a.vertices[0]);
|
|
116
|
+
vertices.push(...trailA(0, vertices));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
const edgeIndex = typeof vertex === 'object' ? vertex.edgeIndexA : vertex;
|
|
121
|
+
const edge = Polygon.getEdge(a, edgeIndex);
|
|
122
|
+
if (typeof vertex === 'object') {
|
|
123
|
+
if ($Point.equals(vertex.point, edge.start)) {
|
|
124
|
+
visitedIntersections[$Point.toString(vertex.point)] = intersections.points[$Point.toString(vertex.point)];
|
|
125
|
+
return vertices;
|
|
126
|
+
}
|
|
127
|
+
const directionalLine = {
|
|
128
|
+
start: vertex.point,
|
|
129
|
+
end: edge.end,
|
|
130
|
+
};
|
|
131
|
+
const intersection = intersections.edges[edge.toString()]
|
|
132
|
+
?.filter((intersection) => intersection.point !== vertex.point && Line.contains(directionalLine, intersection.point))
|
|
133
|
+
.sort((a, b) => $Point.distance(edge.start, a.point) - $Point.distance(edge.start, b.point))[0];
|
|
134
|
+
if (intersection) {
|
|
135
|
+
visitedIntersections[$Point.toString(intersection.point)] = intersection;
|
|
136
|
+
vertices.push(intersection.point);
|
|
137
|
+
vertices.push(...trailB(intersection, vertices));
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
if ($Point.equals(vertices[0], edge.end))
|
|
141
|
+
return vertices;
|
|
142
|
+
vertices.push(edge.end);
|
|
143
|
+
vertices.push(...trailA(vertex.edgeIndexA + 1, vertices));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
const intersection = (vertices.length ? intersections.edges[edge.toString()] : intersections.edges[edge.toString()]?.filter((intersection) => !$Point.equals(intersection.point, edge.start)))?.sort((a, b) => $Point.distance(edge.start, a.point) - $Point.distance(edge.start, b.point))[0];
|
|
148
|
+
if (intersection) {
|
|
149
|
+
if (!$Point.equals(intersection.edgeB.start, intersection.point) && !$Point.equals(intersection.edgeB.end, intersection.point))
|
|
150
|
+
visitedIntersections[$Point.toString(intersection.point)] = intersection;
|
|
151
|
+
if ($Point.equals(vertices[0], intersection.point))
|
|
152
|
+
return vertices;
|
|
153
|
+
vertices.push(intersection.point);
|
|
154
|
+
if (vertices.length > 1) {
|
|
155
|
+
vertices.push(...trailB(intersection, vertices));
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
vertices.push(...trailA(intersection, vertices));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else if (Polygon.containsPoint(b, edge.end)) {
|
|
162
|
+
return trailA(vertex + 1, vertices);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
if ($Point.equals(vertices[0], edge.end))
|
|
166
|
+
return vertices;
|
|
167
|
+
vertices.push(edge.end);
|
|
168
|
+
return trailA(vertex + 1, vertices);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return vertices;
|
|
173
|
+
};
|
|
174
|
+
const trailB = (vertex, vertices = [], trailDirectionFactor) => {
|
|
175
|
+
if (typeof vertex === 'number' && vertex < 0)
|
|
176
|
+
vertex = b.vertices.length - 1;
|
|
177
|
+
const edgeIndex = typeof vertex === 'object' ? vertex.edgeIndexB : vertex;
|
|
178
|
+
const edge = b.getEdge(edgeIndex);
|
|
179
|
+
if (typeof vertex === 'object') {
|
|
180
|
+
let directionFactor;
|
|
181
|
+
if (Polygon.containsPoint(a, edge.start)) {
|
|
182
|
+
directionFactor = -1;
|
|
183
|
+
}
|
|
184
|
+
else if (Polygon.containsPoint(a, edge.end)) {
|
|
185
|
+
directionFactor = 1;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
const intersection = intersections.edges[edge.toString()]
|
|
189
|
+
?.filter((intersection) => intersection.point !== vertex.point &&
|
|
190
|
+
Polygon.containsPoint(a, Line.getMiddle({
|
|
191
|
+
start: vertex.point,
|
|
192
|
+
end: intersection.point,
|
|
193
|
+
})))
|
|
194
|
+
.sort((a, b) => $Point.distance(edge.start, a.point) - $Point.distance(edge.start, b.point))[0];
|
|
195
|
+
visitedIntersections[$Point.toString(intersection.point)] = intersection;
|
|
196
|
+
if ($Point.equals(vertices[0], intersection.point))
|
|
197
|
+
return vertices;
|
|
198
|
+
vertices.push(intersection.point);
|
|
199
|
+
vertices.push(...trailA(intersection, vertices));
|
|
200
|
+
return vertices;
|
|
201
|
+
}
|
|
202
|
+
const targetVertex = directionFactor === 1 ? edge.end : edge.start;
|
|
203
|
+
const directionalLine = {
|
|
204
|
+
start: vertex.point,
|
|
205
|
+
end: targetVertex,
|
|
206
|
+
};
|
|
207
|
+
const intersection = intersections.edges[edge.toString()]
|
|
208
|
+
?.filter((intersection) => intersection.point !== vertex.point && Line.contains(directionalLine, intersection.point))
|
|
209
|
+
.sort((a, b) => $Point.distance(trailDirectionFactor === 1 ? edge.end : edge.start, a.point) - $Point.distance(trailDirectionFactor === 1 ? edge.end : edge.start, b.point))[0];
|
|
210
|
+
if (intersection) {
|
|
211
|
+
visitedIntersections[$Point.toString(intersection.point)] = intersection;
|
|
212
|
+
if ($Point.equals(vertices[0], intersection.point))
|
|
213
|
+
return vertices;
|
|
214
|
+
vertices.push(intersection.point);
|
|
215
|
+
vertices.push(...trailA(intersection, vertices));
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
if ($Point.equals(vertices[0], targetVertex))
|
|
219
|
+
return vertices;
|
|
220
|
+
vertices.push(targetVertex);
|
|
221
|
+
vertices.push(...trailB(vertex.edgeIndexB + directionFactor, vertices, directionFactor));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
const intersection = intersections.edges[edge.toString()]?.sort((a, b) => $Point.distance(trailDirectionFactor === 1 ? edge.end : edge.start, a.point) - $Point.distance(trailDirectionFactor === 1 ? edge.end : edge.start, b.point))[0];
|
|
226
|
+
if (intersection) {
|
|
227
|
+
visitedIntersections[$Point.toString(intersection.point)] = intersection;
|
|
228
|
+
if ($Point.equals(vertices[0], intersection.point))
|
|
229
|
+
return vertices;
|
|
230
|
+
vertices.push(intersection.point);
|
|
231
|
+
vertices.push(...trailA(intersection, vertices));
|
|
232
|
+
}
|
|
233
|
+
else if (Polygon.containsPoint(a, trailDirectionFactor === 1 ? edge.end : edge.start)) {
|
|
234
|
+
if ($Point.equals(vertices[0], trailDirectionFactor === 1 ? edge.end : edge.start))
|
|
235
|
+
return vertices;
|
|
236
|
+
vertices.push(trailDirectionFactor === 1 ? edge.end : edge.start);
|
|
237
|
+
return trailB(vertex + trailDirectionFactor, vertices, trailDirectionFactor);
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
if ($Point.equals(vertices[0], trailDirectionFactor === 1 ? edge.start : edge.end))
|
|
241
|
+
return vertices;
|
|
242
|
+
vertices.push(trailDirectionFactor === 1 ? edge.end : edge.start);
|
|
243
|
+
return trailB(vertex + trailDirectionFactor, vertices, trailDirectionFactor);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return vertices;
|
|
247
|
+
};
|
|
248
|
+
console.group('Start');
|
|
249
|
+
while (Object.keys(visitedIntersections).length !== intersections.intersections.length) {
|
|
250
|
+
let vertices;
|
|
251
|
+
if (Object.keys(visitedIntersections).length === 0)
|
|
252
|
+
vertices = trailA();
|
|
253
|
+
else {
|
|
254
|
+
const intersection = intersections.intersections.find((intersection) => !visitedIntersections[$Point.toString(intersection.point)]);
|
|
255
|
+
console.log({
|
|
256
|
+
intersection,
|
|
257
|
+
visitedIntersections: $Value.clone(visitedIntersections),
|
|
258
|
+
intersections,
|
|
259
|
+
visitedIntersectionsCount: Object.keys(visitedIntersections).length,
|
|
260
|
+
intersectionsCount: intersections.intersections.length,
|
|
261
|
+
});
|
|
262
|
+
vertices = trailA(intersection, [intersection.point]);
|
|
263
|
+
visitedIntersections[$Point.toString(intersection.point)] = intersection;
|
|
264
|
+
}
|
|
265
|
+
polygons.push(new Polygon(vertices));
|
|
266
|
+
}
|
|
267
|
+
console.groupEnd();
|
|
268
|
+
return polygons;
|
|
269
|
+
}
|
|
270
|
+
subtract(polygon) {
|
|
271
|
+
return Polygon.subtract(this, polygon);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Unit } from '../../consts/unit.const';
|
|
2
|
+
export declare class $Number {
|
|
3
|
+
static snap(number: number, value?: number): number;
|
|
4
|
+
static toUnitString(number: number, units: Record<string, number> | typeof Unit): string;
|
|
5
|
+
static round(number: number, decimals?: number): number;
|
|
6
|
+
static min(value: number, min: number): number;
|
|
7
|
+
static max(value: number, max: number): number;
|
|
8
|
+
static clamp(number: number, min: number, max: number): number;
|
|
9
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export class $Number {
|
|
2
|
+
static snap(number, value) {
|
|
3
|
+
return Math.floor(number / value) * value;
|
|
4
|
+
}
|
|
5
|
+
static toUnitString(number, units) {
|
|
6
|
+
const sortedUnits = Object.entries(units).sort(([, a], [, b]) => b - a);
|
|
7
|
+
for (const [unitName, unitValue] of sortedUnits) {
|
|
8
|
+
const converted = number / unitValue;
|
|
9
|
+
if (converted >= 1 || unitValue === sortedUnits[sortedUnits.length - 1][1]) {
|
|
10
|
+
const formatted = Number(converted.toFixed(2));
|
|
11
|
+
return `${formatted} ${unitName}`;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
static round(number, decimals) {
|
|
16
|
+
return Math.round(number * 10 ** decimals) / 10 ** decimals;
|
|
17
|
+
}
|
|
18
|
+
static min(value, min) {
|
|
19
|
+
return Math.max(value, min);
|
|
20
|
+
}
|
|
21
|
+
static max(value, max) {
|
|
22
|
+
return Math.min(value, max);
|
|
23
|
+
}
|
|
24
|
+
static clamp(number, min, max) {
|
|
25
|
+
return Math.min(max, Math.max(min, number));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare class $Object {
|
|
2
|
+
static hasKeys<T = any>(value: any, ...keys: Extract<keyof T, string>[]): boolean;
|
|
3
|
+
static freeze(value: any): void;
|
|
4
|
+
static getDefaults<T extends object>(object: T, defaults?: Partial<T>): T;
|
|
5
|
+
static getPaths(value: any): string[];
|
|
6
|
+
static isEmptyObject(value: any): boolean;
|
|
7
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export class $Object {
|
|
2
|
+
static hasKeys(value, ...keys) {
|
|
3
|
+
return value != null && typeof value === 'object' && keys.every((key) => key in value);
|
|
4
|
+
}
|
|
5
|
+
static freeze(value) {
|
|
6
|
+
if ((value !== null && typeof value === 'object') || typeof value === 'function') {
|
|
7
|
+
Object.freeze(value);
|
|
8
|
+
for (const key in value) {
|
|
9
|
+
$Object.freeze(value[key]);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
static getDefaults(object, defaults = {}) {
|
|
14
|
+
const result = { ...object };
|
|
15
|
+
for (const key in defaults) {
|
|
16
|
+
if (result[key] == null) {
|
|
17
|
+
result[key] = defaults[key];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
static getPaths(value) {
|
|
23
|
+
const paths = [];
|
|
24
|
+
function addPath(path) {
|
|
25
|
+
if (path.length)
|
|
26
|
+
paths.push(path.join('.'));
|
|
27
|
+
}
|
|
28
|
+
function traverse(value, path) {
|
|
29
|
+
if (value == null || typeof value !== 'object') {
|
|
30
|
+
addPath(path);
|
|
31
|
+
}
|
|
32
|
+
else if (Array.isArray(value)) {
|
|
33
|
+
if (value.length === 0) {
|
|
34
|
+
addPath(path);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
for (let i = 0; i < value.length; i++) {
|
|
38
|
+
traverse(value[i], [...path, String(i)]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const keys = Object.keys(value);
|
|
44
|
+
if (keys.length === 0) {
|
|
45
|
+
addPath(path);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
for (const key of keys) {
|
|
49
|
+
traverse(value[key], [...path, key]);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
traverse(value, []);
|
|
55
|
+
return paths;
|
|
56
|
+
}
|
|
57
|
+
static isEmptyObject(value) {
|
|
58
|
+
return typeof value === 'object'
|
|
59
|
+
&& value !== null
|
|
60
|
+
&& !Array.isArray(value)
|
|
61
|
+
&& Object.keys(value).length === 0;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class $Path {
|
|
2
|
+
static isAbsolute(path: string): boolean;
|
|
3
|
+
static relative(path: string): string;
|
|
4
|
+
static absolute(path: string): string;
|
|
5
|
+
static join(...paths: string[]): string;
|
|
6
|
+
static getDirectory(path: string): string;
|
|
7
|
+
static entryName(path: string): string;
|
|
8
|
+
static fileName(path: string): string | null;
|
|
9
|
+
static getExtension(path: string): string | null;
|
|
10
|
+
static setExtension(path: string, extension: string): string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export class $Path {
|
|
2
|
+
static isAbsolute(path) {
|
|
3
|
+
return path.startsWith('/') || path.startsWith('\\');
|
|
4
|
+
}
|
|
5
|
+
static relative(path) {
|
|
6
|
+
return `./${$Path.absolute(path)}`;
|
|
7
|
+
}
|
|
8
|
+
static absolute(path) {
|
|
9
|
+
return $Path.join(path);
|
|
10
|
+
}
|
|
11
|
+
static join(...paths) {
|
|
12
|
+
const separator = '/';
|
|
13
|
+
const path = paths.join(separator);
|
|
14
|
+
const protocol = path.match(/^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/\/?)/)?.[1] ?? '';
|
|
15
|
+
return (protocol +
|
|
16
|
+
path
|
|
17
|
+
.substring(protocol.length)
|
|
18
|
+
.split(/[/\\]+/)
|
|
19
|
+
.reduce((stack, segment) => {
|
|
20
|
+
if (segment === '' || segment === '.')
|
|
21
|
+
return stack;
|
|
22
|
+
if (segment === '..')
|
|
23
|
+
stack.pop();
|
|
24
|
+
else
|
|
25
|
+
stack.push(segment);
|
|
26
|
+
return stack;
|
|
27
|
+
}, [])
|
|
28
|
+
.join(separator));
|
|
29
|
+
}
|
|
30
|
+
static getDirectory(path) {
|
|
31
|
+
const index = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
|
|
32
|
+
if (index > -1)
|
|
33
|
+
return path.substring(0, index);
|
|
34
|
+
return path;
|
|
35
|
+
}
|
|
36
|
+
static entryName(path) {
|
|
37
|
+
const index = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
|
|
38
|
+
return path.substring(index + 1);
|
|
39
|
+
}
|
|
40
|
+
static fileName(path) {
|
|
41
|
+
const name = $Path.entryName(path);
|
|
42
|
+
return name.includes('.') ? name : null;
|
|
43
|
+
}
|
|
44
|
+
static getExtension(path) {
|
|
45
|
+
const indexes = {
|
|
46
|
+
slash: Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\')),
|
|
47
|
+
dot: path.lastIndexOf('.'),
|
|
48
|
+
};
|
|
49
|
+
return indexes.dot > -1 && indexes.dot > indexes.slash ? path.substring(indexes.dot).toLowerCase() : null;
|
|
50
|
+
}
|
|
51
|
+
static setExtension(path, extension) {
|
|
52
|
+
extension = extension.startsWith('.') ? extension : '.' + extension;
|
|
53
|
+
const indexes = {
|
|
54
|
+
slash: Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\')),
|
|
55
|
+
dot: path.lastIndexOf('.'),
|
|
56
|
+
};
|
|
57
|
+
return indexes.dot > indexes.slash ? path.slice(0, indexes.dot) + extension : path + extension;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class $Random {
|
|
2
|
+
/**
|
|
3
|
+
* Returns a random number inclusive to the `min` and `max` number.
|
|
4
|
+
* @param min The minimum value the random number can be.
|
|
5
|
+
* @param max The maximum value the random number can be.
|
|
6
|
+
* @returns A random number inclusive to the `min` and `max` number.
|
|
7
|
+
*/
|
|
8
|
+
static random(min: number, max: number): number;
|
|
9
|
+
static convertSeedToNumber(seed: string): number;
|
|
10
|
+
static generateSeed(length: number): string;
|
|
11
|
+
static seededRandom(seed: string, offset?: number): number;
|
|
12
|
+
static normalizeWeights(items: Record<string, number>): Record<string, number>;
|
|
13
|
+
static getItem(items: Record<string, number>, options?: {
|
|
14
|
+
seed?: string;
|
|
15
|
+
seedOffset?: number;
|
|
16
|
+
}): string;
|
|
17
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export class $Random {
|
|
2
|
+
/**
|
|
3
|
+
* Returns a random number inclusive to the `min` and `max` number.
|
|
4
|
+
* @param min The minimum value the random number can be.
|
|
5
|
+
* @param max The maximum value the random number can be.
|
|
6
|
+
* @returns A random number inclusive to the `min` and `max` number.
|
|
7
|
+
*/
|
|
8
|
+
static random(min, max) {
|
|
9
|
+
return Math.floor(Math.random() * (max - min + 1) + min);
|
|
10
|
+
}
|
|
11
|
+
static convertSeedToNumber(seed) {
|
|
12
|
+
let number = 0;
|
|
13
|
+
for (let i = 0; i < seed.length; i++) {
|
|
14
|
+
number = (number * 31 + seed.charCodeAt(i)) % 100000;
|
|
15
|
+
}
|
|
16
|
+
return number;
|
|
17
|
+
}
|
|
18
|
+
static generateSeed(length) {
|
|
19
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
20
|
+
let seed = '';
|
|
21
|
+
for (let i = 0; i < length; i++) {
|
|
22
|
+
const randomIndex = Math.floor(Math.random() * chars.length);
|
|
23
|
+
seed += chars[randomIndex];
|
|
24
|
+
}
|
|
25
|
+
return seed;
|
|
26
|
+
}
|
|
27
|
+
static seededRandom(seed, offset = 0) {
|
|
28
|
+
const number = $Random.convertSeedToNumber(seed + offset);
|
|
29
|
+
const x = Math.sin(number) * 10000;
|
|
30
|
+
return x - Math.floor(x);
|
|
31
|
+
}
|
|
32
|
+
static normalizeWeights(items) {
|
|
33
|
+
const result = {};
|
|
34
|
+
const total = Object.values(items).reduce((sum, weight) => sum + weight, 0);
|
|
35
|
+
for (const item in items) {
|
|
36
|
+
result[item] = items[item] / total;
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
static getItem(items, options) {
|
|
41
|
+
const random = $Random.seededRandom(options?.seed ?? $Random.generateSeed(10), options?.seedOffset ?? 0);
|
|
42
|
+
const normalizedItems = $Random.normalizeWeights(items);
|
|
43
|
+
const keys = Object.keys(normalizedItems);
|
|
44
|
+
const weights = Object.values(normalizedItems);
|
|
45
|
+
const cumulativeWeights = [];
|
|
46
|
+
let cumulativeSum = 0;
|
|
47
|
+
for (let i = 0; i < weights.length; i++) {
|
|
48
|
+
cumulativeSum += weights[i];
|
|
49
|
+
cumulativeWeights.push(cumulativeSum);
|
|
50
|
+
}
|
|
51
|
+
for (let i = 0; i < cumulativeWeights.length; i++) {
|
|
52
|
+
if (random <= cumulativeWeights[i]) {
|
|
53
|
+
return keys[i];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export class $ReadableStream {
|
|
2
|
+
static async toArrayBuffer(stream) {
|
|
3
|
+
const chunks = [];
|
|
4
|
+
const reader = stream.getReader();
|
|
5
|
+
let totalLength = 0;
|
|
6
|
+
try {
|
|
7
|
+
while (true) {
|
|
8
|
+
const { done, value } = await reader.read();
|
|
9
|
+
if (done)
|
|
10
|
+
break;
|
|
11
|
+
chunks.push(value);
|
|
12
|
+
totalLength += value.length;
|
|
13
|
+
}
|
|
14
|
+
const result = new Uint8Array(totalLength);
|
|
15
|
+
let offset = 0;
|
|
16
|
+
for (const chunk of chunks) {
|
|
17
|
+
result.set(chunk, offset);
|
|
18
|
+
offset += chunk.length;
|
|
19
|
+
}
|
|
20
|
+
return result.buffer;
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
reader.releaseLock();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare abstract class Attribute<T = any> {
|
|
2
|
+
data?: T;
|
|
3
|
+
/** The key used to store the metadata. */
|
|
4
|
+
readonly key: string;
|
|
5
|
+
/** The prototype which the attribute is applied to. */
|
|
6
|
+
prototype: object;
|
|
7
|
+
constructor(prototype: object, data?: T);
|
|
8
|
+
/** Executed when the attribute is applied. */
|
|
9
|
+
onAttributeInit(): void;
|
|
10
|
+
/** Executed when the attribute is removed. */
|
|
11
|
+
onAttributeDestroy(): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { $Id } from '../../id/id.util';
|
|
2
|
+
export class Attribute {
|
|
3
|
+
data;
|
|
4
|
+
/** The key used to store the metadata. */
|
|
5
|
+
key;
|
|
6
|
+
/** The prototype which the attribute is applied to. */
|
|
7
|
+
prototype;
|
|
8
|
+
constructor(prototype, data) {
|
|
9
|
+
this.prototype = prototype;
|
|
10
|
+
this.key = $Id.uuid();
|
|
11
|
+
this.data = data;
|
|
12
|
+
}
|
|
13
|
+
/** Executed when the attribute is applied. */
|
|
14
|
+
onAttributeInit() { }
|
|
15
|
+
/** Executed when the attribute is removed. */
|
|
16
|
+
onAttributeDestroy() { }
|
|
17
|
+
}
|