@jscad/obj-deserializer 2.0.24 → 3.0.0-alpha.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 CHANGED
@@ -3,314 +3,177 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [2.0.24](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.23...@jscad/obj-deserializer@2.0.24) (2023-04-30)
7
-
8
- **Note:** Version bump only for package @jscad/obj-deserializer
6
+ # [3.0.0-alpha.0](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.22...@jscad/obj-deserializer@3.0.0-alpha.0) (2023-10-09)
9
7
 
8
+ ### Bug Fixes
10
9
 
10
+ * **io:** fix io after V3 refactoring ([7a12bbd](https://github.com/jscad/OpenJSCAD.org/commit/7a12bbdb7b4b3df792a4c5b3c8b30a6a985a48f0))
11
11
 
12
+ ### Features
12
13
 
14
+ * **modeling:** reworked exports to expose a flattened API ([8235238](https://github.com/jscad/OpenJSCAD.org/commit/8235238ad63d063f1e501478cae1208deb130a9c))
15
+ * **regl-renderer:** added rollup configuration to create ES6 bundle, adjusted imports and exports ([#1259](https://github.com/jscad/OpenJSCAD.org/issues/1259)) ([47a66bc](https://github.com/jscad/OpenJSCAD.org/commit/47a66bc07a137a748ce8571ea5d043ebaab9418d))
13
16
 
14
- ## [2.0.23](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.22...@jscad/obj-deserializer@2.0.23) (2022-11-26)
17
+ ## [2.0.25](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.24...@jscad/obj-deserializer@2.0.25) (2023-06-27)
15
18
 
16
19
  **Note:** Version bump only for package @jscad/obj-deserializer
17
20
 
21
+ ## [2.0.24](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.23...@jscad/obj-deserializer@2.0.24) (2023-04-30)
18
22
 
23
+ **Note:** Version bump only for package @jscad/obj-deserializer
19
24
 
25
+ ## [2.0.23](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.22...@jscad/obj-deserializer@2.0.23) (2022-11-26)
20
26
 
27
+ **Note:** Version bump only for package @jscad/obj-deserializer
21
28
 
22
29
  ## [2.0.22](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.21...@jscad/obj-deserializer@2.0.22) (2022-08-21)
23
30
 
24
31
  **Note:** Version bump only for package @jscad/obj-deserializer
25
32
 
26
-
27
-
28
-
29
-
30
33
  ## [2.0.21](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.20...@jscad/obj-deserializer@2.0.21) (2022-07-17)
31
34
 
32
35
  **Note:** Version bump only for package @jscad/obj-deserializer
33
36
 
34
-
35
-
36
-
37
-
38
37
  ## [2.0.20](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.19...@jscad/obj-deserializer@2.0.20) (2022-06-12)
39
38
 
40
39
  **Note:** Version bump only for package @jscad/obj-deserializer
41
40
 
42
-
43
-
44
-
45
-
46
41
  ## [2.0.19](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.18...@jscad/obj-deserializer@2.0.19) (2022-05-15)
47
42
 
48
43
  **Note:** Version bump only for package @jscad/obj-deserializer
49
44
 
50
-
51
-
52
-
53
-
54
45
  ## [2.0.18](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.17...@jscad/obj-deserializer@2.0.18) (2022-04-24)
55
46
 
56
47
  **Note:** Version bump only for package @jscad/obj-deserializer
57
48
 
58
-
59
-
60
-
61
-
62
49
  ## [2.0.17](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.16...@jscad/obj-deserializer@2.0.17) (2022-04-03)
63
50
 
64
51
  **Note:** Version bump only for package @jscad/obj-deserializer
65
52
 
66
-
67
-
68
-
69
-
70
53
  ## [2.0.16](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.15...@jscad/obj-deserializer@2.0.16) (2022-04-03)
71
54
 
72
55
  **Note:** Version bump only for package @jscad/obj-deserializer
73
56
 
74
-
75
-
76
-
77
-
78
57
  ## [2.0.15](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.14...@jscad/obj-deserializer@2.0.15) (2022-03-13)
79
58
 
80
59
  **Note:** Version bump only for package @jscad/obj-deserializer
81
60
 
82
-
83
-
84
-
85
-
86
61
  ## [2.0.14](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.13...@jscad/obj-deserializer@2.0.14) (2022-03-06)
87
62
 
88
63
  **Note:** Version bump only for package @jscad/obj-deserializer
89
64
 
90
-
91
-
92
-
93
-
94
65
  ## [2.0.13](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.12...@jscad/obj-deserializer@2.0.13) (2022-02-19)
95
66
 
96
67
  **Note:** Version bump only for package @jscad/obj-deserializer
97
68
 
98
-
99
-
100
-
101
-
102
69
  ## [2.0.12](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.11...@jscad/obj-deserializer@2.0.12) (2021-12-26)
103
70
 
104
71
  **Note:** Version bump only for package @jscad/obj-deserializer
105
72
 
106
-
107
-
108
-
109
-
110
73
  ## [2.0.11](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.10...@jscad/obj-deserializer@2.0.11) (2021-12-11)
111
74
 
112
75
  **Note:** Version bump only for package @jscad/obj-deserializer
113
76
 
114
-
115
-
116
-
117
-
118
77
  ## [2.0.10](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.9...@jscad/obj-deserializer@2.0.10) (2021-11-07)
119
78
 
120
79
  **Note:** Version bump only for package @jscad/obj-deserializer
121
80
 
122
-
123
-
124
-
125
-
126
81
  ## [2.0.9](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.8...@jscad/obj-deserializer@2.0.9) (2021-10-17)
127
82
 
128
83
  **Note:** Version bump only for package @jscad/obj-deserializer
129
84
 
130
-
131
-
132
-
133
-
134
85
  ## [2.0.8](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.7...@jscad/obj-deserializer@2.0.8) (2021-10-04)
135
86
 
136
87
  **Note:** Version bump only for package @jscad/obj-deserializer
137
88
 
138
-
139
-
140
-
141
-
142
89
  ## [2.0.7](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.6...@jscad/obj-deserializer@2.0.7) (2021-09-27)
143
90
 
144
91
  **Note:** Version bump only for package @jscad/obj-deserializer
145
92
 
146
-
147
-
148
-
149
-
150
93
  ## [2.0.6](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.5...@jscad/obj-deserializer@2.0.6) (2021-09-09)
151
94
 
152
95
  **Note:** Version bump only for package @jscad/obj-deserializer
153
96
 
154
-
155
-
156
-
157
-
158
97
  ## [2.0.5](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.4...@jscad/obj-deserializer@2.0.5) (2021-06-20)
159
98
 
160
99
  **Note:** Version bump only for package @jscad/obj-deserializer
161
100
 
162
-
163
-
164
-
165
-
166
101
  ## [2.0.4](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.3...@jscad/obj-deserializer@2.0.4) (2021-06-11)
167
102
 
168
103
  **Note:** Version bump only for package @jscad/obj-deserializer
169
104
 
170
-
171
-
172
-
173
-
174
105
  ## [2.0.3](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.2...@jscad/obj-deserializer@2.0.3) (2021-06-01)
175
106
 
176
107
  **Note:** Version bump only for package @jscad/obj-deserializer
177
108
 
178
-
179
-
180
-
181
-
182
109
  ## [2.0.2](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.0...@jscad/obj-deserializer@2.0.2) (2021-04-20)
183
110
 
184
-
185
111
  ### Bug Fixes
186
112
 
187
113
  * **all:** V2 : several fixes for modeling ([#705](https://github.com/jscad/OpenJSCAD.org/issues/705)) ([62017a4](https://github.com/jscad/OpenJSCAD.org/commit/62017a41214169d6e000f1e0c11aaefdd68e1097))
188
114
 
189
-
190
-
191
-
192
-
193
115
  ## [2.0.1](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.0...@jscad/obj-deserializer@2.0.1) (2021-04-15)
194
116
 
195
-
196
117
  ### Bug Fixes
197
118
 
198
119
  * **all:** V2 : several fixes for modeling ([#705](https://github.com/jscad/OpenJSCAD.org/issues/705)) ([62017a4](https://github.com/jscad/OpenJSCAD.org/commit/62017a41214169d6e000f1e0c11aaefdd68e1097))
199
120
 
200
-
201
-
202
-
203
-
204
121
  # [2.0.0](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.11...@jscad/obj-deserializer@2.0.0) (2021-04-12)
205
122
 
206
123
  **Note:** Version bump only for package @jscad/obj-deserializer
207
124
 
208
-
209
-
210
-
211
-
212
125
  # [2.0.0-alpha.11](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.10...@jscad/obj-deserializer@2.0.0-alpha.11) (2021-03-07)
213
126
 
214
127
  **Note:** Version bump only for package @jscad/obj-deserializer
215
128
 
216
-
217
-
218
-
219
-
220
129
  # [2.0.0-alpha.10](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.9...@jscad/obj-deserializer@2.0.0-alpha.10) (2021-02-07)
221
130
 
222
131
  **Note:** Version bump only for package @jscad/obj-deserializer
223
132
 
224
-
225
-
226
-
227
-
228
133
  # [2.0.0-alpha.9](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.8...@jscad/obj-deserializer@2.0.0-alpha.9) (2021-01-02)
229
134
 
230
135
  **Note:** Version bump only for package @jscad/obj-deserializer
231
136
 
232
-
233
-
234
-
235
-
236
137
  # [2.0.0-alpha.8](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.7...@jscad/obj-deserializer@2.0.0-alpha.8) (2020-12-04)
237
138
 
238
139
  **Note:** Version bump only for package @jscad/obj-deserializer
239
140
 
240
-
241
-
242
-
243
-
244
141
  # [2.0.0-alpha.7](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.6...@jscad/obj-deserializer@2.0.0-alpha.7) (2020-11-07)
245
142
 
246
143
  **Note:** Version bump only for package @jscad/obj-deserializer
247
144
 
248
-
249
-
250
-
251
-
252
145
  # [2.0.0-alpha.6](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.5...@jscad/obj-deserializer@2.0.0-alpha.6) (2020-10-11)
253
146
 
254
-
255
147
  ### Bug Fixes
256
148
 
257
149
  * **all:** V2 : several fixes for modeling ([#705](https://github.com/jscad/OpenJSCAD.org/issues/705)) ([62017a4](https://github.com/jscad/OpenJSCAD.org/commit/62017a41214169d6e000f1e0c11aaefdd68e1097))
258
150
 
259
-
260
-
261
-
262
-
263
151
  # [2.0.0-alpha.5](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.4...@jscad/obj-deserializer@2.0.0-alpha.5) (2020-09-29)
264
152
 
265
153
  **Note:** Version bump only for package @jscad/obj-deserializer
266
154
 
267
-
268
-
269
-
270
-
271
155
  # [2.0.0-alpha.4](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.3...@jscad/obj-deserializer@2.0.0-alpha.4) (2020-09-28)
272
156
 
273
157
  **Note:** Version bump only for package @jscad/obj-deserializer
274
158
 
275
-
276
-
277
-
278
-
279
159
  # [2.0.0-alpha.3](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.2...@jscad/obj-deserializer@2.0.0-alpha.3) (2020-09-19)
280
160
 
281
161
  **Note:** Version bump only for package @jscad/obj-deserializer
282
162
 
283
-
284
-
285
-
286
-
287
163
  # [2.0.0-alpha.2](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.1...@jscad/obj-deserializer@2.0.0-alpha.2) (2020-09-08)
288
164
 
289
165
  **Note:** Version bump only for package @jscad/obj-deserializer
290
166
 
291
-
292
-
293
-
294
-
295
167
  # [2.0.0-alpha.1](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/obj-deserializer@2.0.0-alpha.0...@jscad/obj-deserializer@2.0.0-alpha.1) (2020-08-19)
296
168
 
297
169
  **Note:** Version bump only for package @jscad/obj-deserializer
298
170
 
299
-
300
-
301
-
302
-
303
171
  # 2.0.0-alpha.0 (2020-08-13)
304
172
 
305
-
306
173
  ### Bug Fixes
307
174
 
308
175
  * **obj-deserializer:** corrected stringify() to supply V2 require and export ([#497](https://github.com/jscad/OpenJSCAD.org/issues/497)) ([1fd11ae](https://github.com/jscad/OpenJSCAD.org/commit/1fd11aeb1e1a309a3b87dd542d43870bceb9c903))
309
176
 
310
-
311
-
312
-
313
-
314
177
  ### Features
315
178
 
316
179
  * **obj-deserializer:** overhaul for V2 branch (#469)
@@ -319,69 +182,43 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
319
182
  <a name="0.2.3"></a>
320
183
  ## [0.2.3](https://github.com/jscad/io/compare/@jscad/obj-deserializer@0.2.2...@jscad/obj-deserializer@0.2.3) (2018-11-25)
321
184
 
322
-
323
-
324
-
325
185
  **Note:** Version bump only for package @jscad/obj-deserializer
326
186
 
327
187
  <a name="0.2.2"></a>
328
188
  ## [0.2.2](https://github.com/jscad/io/compare/@jscad/obj-deserializer@0.2.1...@jscad/obj-deserializer@0.2.2) (2018-11-22)
329
189
 
330
-
331
-
332
-
333
190
  **Note:** Version bump only for package @jscad/obj-deserializer
334
191
 
335
192
  <a name="0.2.1"></a>
336
193
  ## [0.2.1](https://github.com/jscad/io/compare/@jscad/obj-deserializer@0.2.0...@jscad/obj-deserializer@0.2.1) (2017-12-14)
337
194
 
338
-
339
-
340
-
341
195
  **Note:** Version bump only for package @jscad/obj-deserializer
342
196
 
343
197
  <a name="0.2.0"></a>
344
198
  # [0.2.0](https://github.com/jscad/io/compare/@jscad/obj-deserializer@0.1.0...@jscad/obj-deserializer@0.2.0) (2017-11-29)
345
199
 
346
-
347
200
  ### Features
348
201
 
349
202
  * add support for a status callback for de/serialization progress ([#49](https://github.com/jscad/io/issues/49)) ([f457cdb](https://github.com/jscad/io/commit/f457cdb))
350
203
 
351
-
352
-
353
-
354
204
  <a name="0.1.0"></a>
355
205
  # [0.1.0](https://github.com/jscad/io/compare/@jscad/obj-deserializer@0.0.4...@jscad/obj-deserializer@0.1.0) (2017-11-14)
356
206
 
357
-
358
207
  ### Features
359
208
 
360
209
  * **deserializers:** added csg output capabilities to amf & obj deserializers & basic tests ([#47](https://github.com/jscad/io/issues/47)) ([abf3040](https://github.com/jscad/io/commit/abf3040))
361
210
 
362
-
363
-
364
-
365
211
  <a name="0.0.4"></a>
366
212
  ## [0.0.4](https://github.com/jscad/io/compare/@jscad/obj-deserializer@0.0.3...@jscad/obj-deserializer@0.0.4) (2017-11-04)
367
213
 
368
-
369
-
370
-
371
214
  **Note:** Version bump only for package @jscad/obj-deserializer
372
215
 
373
216
  <a name="0.0.3"></a>
374
217
  ## [0.0.3](https://github.com/jscad/io/compare/@jscad/obj-deserializer@0.0.2...@jscad/obj-deserializer@0.0.3) (2017-10-10)
375
218
 
376
-
377
-
378
-
379
219
  **Note:** Version bump only for package @jscad/obj-deserializer
380
220
 
381
221
  <a name="0.0.2"></a>
382
222
  ## 0.0.2 (2017-10-10)
383
223
 
384
-
385
-
386
-
387
224
  **Note:** Version bump only for package @jscad/obj-deserializer
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  [![License](https://img.shields.io/github/license/jscad/OpenJSCAD.org)](https://github.com/jscad/OpenJSCAD.org/blob/master/LICENSE)
10
10
 
11
11
  [![User Group](https://img.shields.io/badge/maintained%20by-user%20group-blue)](https://openjscad.nodebb.com/)
12
- [![Lerna](https://img.shields.io/badge/maintained%20with-lerna-blue)](https://lerna.js.org/)
12
+ [![lerna--lite](https://img.shields.io/badge/maintained%20with-lerna--lite-e137ff)](https://github.com/ghiscoding/lerna-lite)
13
13
  [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-blue)](https://standardjs.com)
14
14
 
15
15
  [![Backers](https://img.shields.io/opencollective/backers/openjscad)](https://opencollective.com/openjscad)
@@ -77,5 +77,7 @@ Small Note: If editing this README, please conform to the [standard-readme](http
77
77
 
78
78
  ## License
79
79
 
80
+ Copyright (c) JSCAD Organization
81
+
80
82
  [The MIT License (MIT)](../../LICENSE)
81
83
  (unless specified otherwise)
@@ -0,0 +1,13 @@
1
+ /**
2
+ * OBJ Deserializer for JSCAD
3
+ * @module @jscad/obj-deserializer
4
+ * @version 3.0.0-alpha.0
5
+ * @license MIT
6
+ */
7
+ /**
8
+ * Constructive Solid Geometry (CSG) Library for JSCAD
9
+ * @module @jscad/modeling
10
+ * @version 3.0.0-alpha.0
11
+ * @license MIT
12
+ */
13
+ const cssColors={black:[0,0,0],silver:[192/255,192/255,192/255],gray:[128/255,128/255,128/255],white:[1,1,1],maroon:[128/255,0,0],red:[1,0,0],purple:[128/255,0,128/255],fuchsia:[1,0,1],green:[0,128/255,0],lime:[0,1,0],olive:[128/255,128/255,0],yellow:[1,1,0],navy:[0,0,128/255],blue:[0,0,1],teal:[0,128/255,128/255],aqua:[0,1,1],aliceblue:[240/255,248/255,1],antiquewhite:[250/255,235/255,215/255],aquamarine:[127/255,1,212/255],azure:[240/255,1,1],beige:[245/255,245/255,220/255],bisque:[1,228/255,196/255],blanchedalmond:[1,235/255,205/255],blueviolet:[138/255,43/255,226/255],brown:[165/255,42/255,42/255],burlywood:[222/255,184/255,135/255],cadetblue:[95/255,158/255,160/255],chartreuse:[127/255,1,0],chocolate:[210/255,105/255,30/255],coral:[1,127/255,80/255],cornflowerblue:[100/255,149/255,237/255],cornsilk:[1,248/255,220/255],crimson:[220/255,20/255,60/255],cyan:[0,1,1],darkblue:[0,0,139/255],darkcyan:[0,139/255,139/255],darkgoldenrod:[184/255,134/255,11/255],darkgray:[169/255,169/255,169/255],darkgreen:[0,100/255,0],darkgrey:[169/255,169/255,169/255],darkkhaki:[189/255,183/255,107/255],darkmagenta:[139/255,0,139/255],darkolivegreen:[85/255,107/255,47/255],darkorange:[1,140/255,0],darkorchid:[.6,50/255,.8],darkred:[139/255,0,0],darksalmon:[233/255,150/255,122/255],darkseagreen:[143/255,188/255,143/255],darkslateblue:[72/255,61/255,139/255],darkslategray:[47/255,79/255,79/255],darkslategrey:[47/255,79/255,79/255],darkturquoise:[0,206/255,209/255],darkviolet:[148/255,0,211/255],deeppink:[1,20/255,147/255],deepskyblue:[0,191/255,1],dimgray:[105/255,105/255,105/255],dimgrey:[105/255,105/255,105/255],dodgerblue:[30/255,144/255,1],firebrick:[178/255,34/255,34/255],floralwhite:[1,250/255,240/255],forestgreen:[34/255,139/255,34/255],gainsboro:[220/255,220/255,220/255],ghostwhite:[248/255,248/255,1],gold:[1,215/255,0],goldenrod:[218/255,165/255,32/255],greenyellow:[173/255,1,47/255],grey:[128/255,128/255,128/255],honeydew:[240/255,1,240/255],hotpink:[1,105/255,180/255],indianred:[205/255,92/255,92/255],indigo:[75/255,0,130/255],ivory:[1,1,240/255],khaki:[240/255,230/255,140/255],lavender:[230/255,230/255,250/255],lavenderblush:[1,240/255,245/255],lawngreen:[124/255,252/255,0],lemonchiffon:[1,250/255,205/255],lightblue:[173/255,216/255,230/255],lightcoral:[240/255,128/255,128/255],lightcyan:[224/255,1,1],lightgoldenrodyellow:[250/255,250/255,210/255],lightgray:[211/255,211/255,211/255],lightgreen:[144/255,238/255,144/255],lightgrey:[211/255,211/255,211/255],lightpink:[1,182/255,193/255],lightsalmon:[1,160/255,122/255],lightseagreen:[32/255,178/255,170/255],lightskyblue:[135/255,206/255,250/255],lightslategray:[119/255,136/255,.6],lightslategrey:[119/255,136/255,.6],lightsteelblue:[176/255,196/255,222/255],lightyellow:[1,1,224/255],limegreen:[50/255,205/255,50/255],linen:[250/255,240/255,230/255],magenta:[1,0,1],mediumaquamarine:[.4,205/255,170/255],mediumblue:[0,0,205/255],mediumorchid:[186/255,85/255,211/255],mediumpurple:[147/255,112/255,219/255],mediumseagreen:[60/255,179/255,113/255],mediumslateblue:[123/255,104/255,238/255],mediumspringgreen:[0,250/255,154/255],mediumturquoise:[72/255,209/255,.8],mediumvioletred:[199/255,21/255,133/255],midnightblue:[25/255,25/255,112/255],mintcream:[245/255,1,250/255],mistyrose:[1,228/255,225/255],moccasin:[1,228/255,181/255],navajowhite:[1,222/255,173/255],oldlace:[253/255,245/255,230/255],olivedrab:[107/255,142/255,35/255],orange:[1,165/255,0],orangered:[1,69/255,0],orchid:[218/255,112/255,214/255],palegoldenrod:[238/255,232/255,170/255],palegreen:[152/255,251/255,152/255],paleturquoise:[175/255,238/255,238/255],palevioletred:[219/255,112/255,147/255],papayawhip:[1,239/255,213/255],peachpuff:[1,218/255,185/255],peru:[205/255,133/255,63/255],pink:[1,192/255,203/255],plum:[221/255,160/255,221/255],powderblue:[176/255,224/255,230/255],rosybrown:[188/255,143/255,143/255],royalblue:[65/255,105/255,225/255],saddlebrown:[139/255,69/255,19/255],salmon:[250/255,128/255,114/255],sandybrown:[244/255,164/255,96/255],seagreen:[46/255,139/255,87/255],seashell:[1,245/255,238/255],sienna:[160/255,82/255,45/255],skyblue:[135/255,206/255,235/255],slateblue:[106/255,90/255,205/255],slategray:[112/255,128/255,144/255],slategrey:[112/255,128/255,144/255],snow:[1,250/255,250/255],springgreen:[0,1,127/255],steelblue:[70/255,130/255,180/255],tan:[210/255,180/255,140/255],thistle:[216/255,191/255,216/255],tomato:[1,99/255,71/255],turquoise:[64/255,224/255,208/255],violet:[238/255,130/255,238/255],wheat:[245/255,222/255,179/255],whitesmoke:[245/255,245/255,245/255],yellowgreen:[154/255,205/255,50/255]},clone$a=matrix=>{const out=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];return out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out},copy$5=(out,matrix)=>(out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out),EPS=1e-5,TAU=2*Math.PI,rezero=n=>Math.abs(n)<1e-13?0:n,sin=radians=>rezero(Math.sin(radians)),cos=radians=>rezero(Math.cos(radians)),identity=out=>(out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out),fromRotation=(out,rad,axis)=>{let[x,y,z]=axis;const lengthSquared=x*x+y*y+z*z;if(Math.abs(lengthSquared)<EPS)return identity(out);const len=1/Math.sqrt(lengthSquared);x*=len,y*=len,z*=len;const s=sin(rad),c=cos(rad),t=1-c;return out[0]=x*x*t+c,out[1]=y*x*t+z*s,out[2]=z*x*t-y*s,out[3]=0,out[4]=x*y*t-z*s,out[5]=y*y*t+c,out[6]=z*y*t+x*s,out[7]=0,out[8]=x*z*t+y*s,out[9]=y*z*t-x*s,out[10]=z*z*t+c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},abs$1=(out,vector)=>(out[0]=Math.abs(vector[0]),out[1]=Math.abs(vector[1]),out[2]=Math.abs(vector[2]),out),add$1=(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out[2]=a[2]+b[2],out),dot$2=(a,b)=>a[0]*b[0]+a[1]*b[1]+a[2]*b[2],clone$9=vector=>{const out=[0,0,0];return out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out},copy$4=(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out),cross$1=(out,a,b)=>{const ax=a[0],ay=a[1],az=a[2],bx=b[0],by=b[1],bz=b[2];return out[0]=ay*bz-az*by,out[1]=az*bx-ax*bz,out[2]=ax*by-ay*bx,out},equals$7=(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2],fromScalar$2=(out,scalar)=>(out[0]=scalar,out[1]=scalar,out[2]=scalar,out),fromValues$3=(x,y,z)=>{const out=[0,0,0];return out[0]=x,out[1]=y,out[2]=z,out},fromVec2=(out,vector,z=0)=>(out[0]=vector[0],out[1]=vector[1],out[2]=z,out),length$2=vector=>{const x=vector[0],y=vector[1],z=vector[2];return Math.sqrt(x*x+y*y+z*z)},max$2=(out,a,b)=>(out[0]=Math.max(a[0],b[0]),out[1]=Math.max(a[1],b[1]),out[2]=Math.max(a[2],b[2]),out),min$2=(out,a,b)=>(out[0]=Math.min(a[0],b[0]),out[1]=Math.min(a[1],b[1]),out[2]=Math.min(a[2],b[2]),out),multiply$2=(out,a,b)=>(out[0]=a[0]*b[0],out[1]=a[1]*b[1],out[2]=a[2]*b[2],out),negate$1=(out,vector)=>(out[0]=-vector[0],out[1]=-vector[1],out[2]=-vector[2],out),normalize$1=(out,vector)=>{const x=vector[0],y=vector[1],z=vector[2];let len=x*x+y*y+z*z;return len>0&&(len=1/Math.sqrt(len)),out[0]=x*len,out[1]=y*len,out[2]=z*len,out},orthogonal=(out,vector)=>{const bV=abs$1([0,0,0],vector),b0=0+(bV[0]<bV[1]&&bV[0]<bV[2]),b1=0+(bV[1]<=bV[0]&&bV[1]<bV[2]),b2=0+(bV[2]<=bV[0]&&bV[2]<=bV[1]);return cross$1(out,vector,[b0,b1,b2])},scale$3=(out,vector,amount)=>(out[0]=vector[0]*amount,out[1]=vector[1]*amount,out[2]=vector[2]*amount,out),squaredDistance$1=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1],z=b[2]-a[2];return x*x+y*y+z*z},subtract$3=(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out[2]=a[2]-b[2],out),toString$b=vec=>`[${vec[0].toFixed(7)}, ${vec[1].toFixed(7)}, ${vec[2].toFixed(7)}]`,transform$c=(out,vector,matrix)=>{const x=vector[0],y=vector[1],z=vector[2];let w=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15];return w=w||1,out[0]=(matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12])/w,out[1]=(matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13])/w,out[2]=(matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14])/w,out};Object.freeze({__proto__:null,abs:abs$1,add:add$1,angle:(a,b)=>{const ax=a[0],ay=a[1],az=a[2],bx=b[0],by=b[1],bz=b[2],mag=Math.sqrt(ax*ax+ay*ay+az*az)*Math.sqrt(bx*bx+by*by+bz*bz),cosine=mag&&dot$2(a,b)/mag;return Math.acos(Math.min(Math.max(cosine,-1),1))},clone:clone$9,copy:copy$4,create:()=>[0,0,0],cross:cross$1,distance:(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1],z=b[2]-a[2];return Math.sqrt(x*x+y*y+z*z)},divide:(out,a,b)=>(out[0]=a[0]/b[0],out[1]=a[1]/b[1],out[2]=a[2]/b[2],out),dot:dot$2,equals:equals$7,fromScalar:fromScalar$2,fromValues:fromValues$3,fromVec2:fromVec2,length:length$2,lerp:(out,a,b,t)=>(out[0]=a[0]+t*(b[0]-a[0]),out[1]=a[1]+t*(b[1]-a[1]),out[2]=a[2]+t*(b[2]-a[2]),out),max:max$2,min:min$2,multiply:multiply$2,negate:negate$1,normalize:normalize$1,orthogonal:orthogonal,rotateX:(out,vector,origin,radians)=>{const p=[],r=[];return p[0]=vector[0]-origin[0],p[1]=vector[1]-origin[1],p[2]=vector[2]-origin[2],r[0]=p[0],r[1]=p[1]*Math.cos(radians)-p[2]*Math.sin(radians),r[2]=p[1]*Math.sin(radians)+p[2]*Math.cos(radians),out[0]=r[0]+origin[0],out[1]=r[1]+origin[1],out[2]=r[2]+origin[2],out},rotateY:(out,vector,origin,radians)=>{const p=[],r=[];return p[0]=vector[0]-origin[0],p[1]=vector[1]-origin[1],p[2]=vector[2]-origin[2],r[0]=p[2]*Math.sin(radians)+p[0]*Math.cos(radians),r[1]=p[1],r[2]=p[2]*Math.cos(radians)-p[0]*Math.sin(radians),out[0]=r[0]+origin[0],out[1]=r[1]+origin[1],out[2]=r[2]+origin[2],out},rotateZ:(out,vector,origin,radians)=>{const p=[],r=[];return p[0]=vector[0]-origin[0],p[1]=vector[1]-origin[1],r[0]=p[0]*Math.cos(radians)-p[1]*Math.sin(radians),r[1]=p[0]*Math.sin(radians)+p[1]*Math.cos(radians),out[0]=r[0]+origin[0],out[1]=r[1]+origin[1],out[2]=vector[2],out},scale:scale$3,snap:(out,vector,epsilon)=>(out[0]=Math.round(vector[0]/epsilon)*epsilon+0,out[1]=Math.round(vector[1]/epsilon)*epsilon+0,out[2]=Math.round(vector[2]/epsilon)*epsilon+0,out),squaredDistance:squaredDistance$1,squaredLength:vector=>{const x=vector[0],y=vector[1],z=vector[2];return x*x+y*y+z*z},subtract:subtract$3,toString:toString$b,transform:transform$c});const isIdentity=matrix=>1===matrix[0]&&0===matrix[1]&&0===matrix[2]&&0===matrix[3]&&0===matrix[4]&&1===matrix[5]&&0===matrix[6]&&0===matrix[7]&&0===matrix[8]&&0===matrix[9]&&1===matrix[10]&&0===matrix[11]&&0===matrix[12]&&0===matrix[13]&&0===matrix[14]&&1===matrix[15],isMirroring=matrix=>{const x=matrix[4]*matrix[9]-matrix[8]*matrix[5],y=matrix[8]*matrix[1]-matrix[0]*matrix[9],z=matrix[0]*matrix[5]-matrix[4]*matrix[1];return x*matrix[2]+y*matrix[6]+z*matrix[10]<0},isZero=num=>Math.abs(num)<Number.EPSILON,multiply$1=(out,a,b)=>{const a00=a[0],a01=a[1],a02=a[2],a03=a[3],a10=a[4],a11=a[5],a12=a[6],a13=a[7],a20=a[8],a21=a[9],a22=a[10],a23=a[11],a30=a[12],a31=a[13],a32=a[14],a33=a[15];let b0=b[0],b1=b[1],b2=b[2],b3=b[3];return out[0]=b0*a00+b1*a10+b2*a20+b3*a30,out[1]=b0*a01+b1*a11+b2*a21+b3*a31,out[2]=b0*a02+b1*a12+b2*a22+b3*a32,out[3]=b0*a03+b1*a13+b2*a23+b3*a33,b0=b[4],b1=b[5],b2=b[6],b3=b[7],out[4]=b0*a00+b1*a10+b2*a20+b3*a30,out[5]=b0*a01+b1*a11+b2*a21+b3*a31,out[6]=b0*a02+b1*a12+b2*a22+b3*a32,out[7]=b0*a03+b1*a13+b2*a23+b3*a33,b0=b[8],b1=b[9],b2=b[10],b3=b[11],out[8]=b0*a00+b1*a10+b2*a20+b3*a30,out[9]=b0*a01+b1*a11+b2*a21+b3*a31,out[10]=b0*a02+b1*a12+b2*a22+b3*a32,out[11]=b0*a03+b1*a13+b2*a23+b3*a33,b0=b[12],b1=b[13],b2=b[14],b3=b[15],out[12]=b0*a00+b1*a10+b2*a20+b3*a30,out[13]=b0*a01+b1*a11+b2*a21+b3*a31,out[14]=b0*a02+b1*a12+b2*a22+b3*a32,out[15]=b0*a03+b1*a13+b2*a23+b3*a33,out};Object.freeze({__proto__:null,add:(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out[2]=a[2]+b[2],out[3]=a[3]+b[3],out[4]=a[4]+b[4],out[5]=a[5]+b[5],out[6]=a[6]+b[6],out[7]=a[7]+b[7],out[8]=a[8]+b[8],out[9]=a[9]+b[9],out[10]=a[10]+b[10],out[11]=a[11]+b[11],out[12]=a[12]+b[12],out[13]=a[13]+b[13],out[14]=a[14]+b[14],out[15]=a[15]+b[15],out),clone:clone$a,copy:copy$5,create:()=>[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],equals:(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3]&&a[4]===b[4]&&a[5]===b[5]&&a[6]===b[6]&&a[7]===b[7]&&a[8]===b[8]&&a[9]===b[9]&&a[10]===b[10]&&a[11]===b[11]&&a[12]===b[12]&&a[13]===b[13]&&a[14]===b[14]&&a[15]===b[15],fromRotation:fromRotation,fromScaling:(out,vector)=>(out[0]=vector[0],out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=vector[1],out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=vector[2],out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out),fromTaitBryanRotation:(out,yaw,pitch,roll)=>{const sy=sin(yaw),cy=cos(yaw),sp=sin(pitch),cp=cos(pitch),sr=sin(roll),cr=cos(roll);return out[0]=cp*cy,out[1]=cp*sy,out[2]=-sp,out[3]=0,out[4]=sr*sp*cy-cr*sy,out[5]=cr*cy+sr*sp*sy,out[6]=sr*cp,out[7]=0,out[8]=sr*sy+cr*sp*cy,out[9]=cr*sp*sy-sr*cy,out[10]=cr*cp,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromTranslation:(out,vector)=>(out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=vector[0],out[13]=vector[1],out[14]=vector[2],out[15]=1,out),fromValues:(m00,m01,m02,m03,m10,m11,m12,m13,m20,m21,m22,m23,m30,m31,m32,m33)=>{const out=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];return out[0]=m00,out[1]=m01,out[2]=m02,out[3]=m03,out[4]=m10,out[5]=m11,out[6]=m12,out[7]=m13,out[8]=m20,out[9]=m21,out[10]=m22,out[11]=m23,out[12]=m30,out[13]=m31,out[14]=m32,out[15]=m33,out},fromVectorRotation:(out,source,target)=>{const sourceNormal=normalize$1([0,0,0],source),targetNormal=normalize$1([0,0,0],target),axis=cross$1([0,0,0],targetNormal,sourceNormal),cosA=dot$2(targetNormal,sourceNormal);if(-1===cosA)return fromRotation(out,Math.PI,orthogonal(axis,sourceNormal));const k=1/(1+cosA);return out[0]=axis[0]*axis[0]*k+cosA,out[1]=axis[1]*axis[0]*k-axis[2],out[2]=axis[2]*axis[0]*k+axis[1],out[3]=0,out[4]=axis[0]*axis[1]*k+axis[2],out[5]=axis[1]*axis[1]*k+cosA,out[6]=axis[2]*axis[1]*k-axis[0],out[7]=0,out[8]=axis[0]*axis[2]*k-axis[1],out[9]=axis[1]*axis[2]*k+axis[0],out[10]=axis[2]*axis[2]*k+cosA,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromXRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=c,out[6]=s,out[7]=0,out[8]=0,out[9]=-s,out[10]=c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromYRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=c,out[1]=0,out[2]=-s,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=s,out[9]=0,out[10]=c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromZRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=c,out[1]=s,out[2]=0,out[3]=0,out[4]=-s,out[5]=c,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},identity:identity,invert:(out,matrix)=>{const a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],a30=matrix[12],a31=matrix[13],a32=matrix[14],a33=matrix[15],b00=a00*a11-a01*a10,b01=a00*a12-a02*a10,b02=a00*a13-a03*a10,b03=a01*a12-a02*a11,b04=a01*a13-a03*a11,b05=a02*a13-a03*a12,b06=a20*a31-a21*a30,b07=a20*a32-a22*a30,b08=a20*a33-a23*a30,b09=a21*a32-a22*a31,b10=a21*a33-a23*a31,b11=a22*a33-a23*a32;let det=b00*b11-b01*b10+b02*b09+b03*b08-b04*b07+b05*b06;return det?(det=1/det,out[0]=(a11*b11-a12*b10+a13*b09)*det,out[1]=(a02*b10-a01*b11-a03*b09)*det,out[2]=(a31*b05-a32*b04+a33*b03)*det,out[3]=(a22*b04-a21*b05-a23*b03)*det,out[4]=(a12*b08-a10*b11-a13*b07)*det,out[5]=(a00*b11-a02*b08+a03*b07)*det,out[6]=(a32*b02-a30*b05-a33*b01)*det,out[7]=(a20*b05-a22*b02+a23*b01)*det,out[8]=(a10*b10-a11*b08+a13*b06)*det,out[9]=(a01*b08-a00*b10-a03*b06)*det,out[10]=(a30*b04-a31*b02+a33*b00)*det,out[11]=(a21*b02-a20*b04-a23*b00)*det,out[12]=(a11*b07-a10*b09-a12*b06)*det,out[13]=(a00*b09-a01*b07+a02*b06)*det,out[14]=(a31*b01-a30*b03-a32*b00)*det,out[15]=(a20*b03-a21*b01+a22*b00)*det,out):null},isIdentity:isIdentity,isMirroring:isMirroring,isOnlyTransformScale:matrix=>isZero(matrix[1])&&isZero(matrix[2])&&isZero(matrix[3])&&isZero(matrix[4])&&isZero(matrix[6])&&isZero(matrix[7])&&isZero(matrix[8])&&isZero(matrix[9])&&isZero(matrix[11])&&1===matrix[15],mirrorByPlane:(out,plane)=>{const[nx,ny,nz,w]=plane;return out[0]=1-2*nx*nx,out[1]=-2*ny*nx,out[2]=-2*nz*nx,out[3]=0,out[4]=-2*nx*ny,out[5]=1-2*ny*ny,out[6]=-2*nz*ny,out[7]=0,out[8]=-2*nx*nz,out[9]=-2*ny*nz,out[10]=1-2*nz*nz,out[11]=0,out[12]=2*nx*w,out[13]=2*ny*w,out[14]=2*nz*w,out[15]=1,out},multiply:multiply$1,rotate:(out,matrix,radians,axis)=>{let[x,y,z]=axis;const lengthSquared=x*x+y*y+z*z;if(Math.abs(lengthSquared)<EPS)return copy$5(out,matrix);const len=1/Math.sqrt(lengthSquared);x*=len,y*=len,z*=len;const s=sin(radians),c=cos(radians),t=1-c,a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],b00=x*x*t+c,b01=y*x*t+z*s,b02=z*x*t-y*s,b10=x*y*t-z*s,b11=y*y*t+c,b12=z*y*t+x*s,b20=x*z*t+y*s,b21=y*z*t-x*s,b22=z*z*t+c;return out[0]=a00*b00+a10*b01+a20*b02,out[1]=a01*b00+a11*b01+a21*b02,out[2]=a02*b00+a12*b01+a22*b02,out[3]=a03*b00+a13*b01+a23*b02,out[4]=a00*b10+a10*b11+a20*b12,out[5]=a01*b10+a11*b11+a21*b12,out[6]=a02*b10+a12*b11+a22*b12,out[7]=a03*b10+a13*b11+a23*b12,out[8]=a00*b20+a10*b21+a20*b22,out[9]=a01*b20+a11*b21+a21*b22,out[10]=a02*b20+a12*b21+a22*b22,out[11]=a03*b20+a13*b21+a23*b22,matrix!==out&&(out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out},rotateX:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11];return matrix!==out&&(out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[4]=a10*c+a20*s,out[5]=a11*c+a21*s,out[6]=a12*c+a22*s,out[7]=a13*c+a23*s,out[8]=a20*c-a10*s,out[9]=a21*c-a11*s,out[10]=a22*c-a12*s,out[11]=a23*c-a13*s,out},rotateY:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11];return matrix!==out&&(out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[0]=a00*c-a20*s,out[1]=a01*c-a21*s,out[2]=a02*c-a22*s,out[3]=a03*c-a23*s,out[8]=a00*s+a20*c,out[9]=a01*s+a21*c,out[10]=a02*s+a22*c,out[11]=a03*s+a23*c,out},rotateZ:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7];return matrix!==out&&(out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[0]=a00*c+a10*s,out[1]=a01*c+a11*s,out[2]=a02*c+a12*s,out[3]=a03*c+a13*s,out[4]=a10*c-a00*s,out[5]=a11*c-a01*s,out[6]=a12*c-a02*s,out[7]=a13*c-a03*s,out},scale:(out,matrix,dimensions)=>{const x=dimensions[0],y=dimensions[1],z=dimensions[2];return out[0]=matrix[0]*x,out[1]=matrix[1]*x,out[2]=matrix[2]*x,out[3]=matrix[3]*x,out[4]=matrix[4]*y,out[5]=matrix[5]*y,out[6]=matrix[6]*y,out[7]=matrix[7]*y,out[8]=matrix[8]*z,out[9]=matrix[9]*z,out[10]=matrix[10]*z,out[11]=matrix[11]*z,out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out},subtract:(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out[2]=a[2]-b[2],out[3]=a[3]-b[3],out[4]=a[4]-b[4],out[5]=a[5]-b[5],out[6]=a[6]-b[6],out[7]=a[7]-b[7],out[8]=a[8]-b[8],out[9]=a[9]-b[9],out[10]=a[10]-b[10],out[11]=a[11]-b[11],out[12]=a[12]-b[12],out[13]=a[13]-b[13],out[14]=a[14]-b[14],out[15]=a[15]-b[15],out),toString:mat=>mat.map((n=>n.toFixed(7))).toString(),translate:(out,matrix,offsets)=>{const x=offsets[0],y=offsets[1],z=offsets[2];let a00,a01,a02,a03,a10,a11,a12,a13,a20,a21,a22,a23;return matrix===out?(out[12]=matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12],out[13]=matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13],out[14]=matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14],out[15]=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15]):(a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],out[0]=a00,out[1]=a01,out[2]=a02,out[3]=a03,out[4]=a10,out[5]=a11,out[6]=a12,out[7]=a13,out[8]=a20,out[9]=a21,out[10]=a22,out[11]=a23,out[12]=a00*x+a10*y+a20*z+matrix[12],out[13]=a01*x+a11*y+a21*z+matrix[13],out[14]=a02*x+a12*y+a22*z+matrix[14],out[15]=a03*x+a13*y+a23*z+matrix[15]),out}});const create$a=(outlines=[])=>({outlines:outlines,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),add=(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out),angleRadians=vector=>Math.atan2(vector[1],vector[0]),angleDegrees=vector=>57.29577951308232*angleRadians(vector),clone$8=vector=>{const out=[0,0];return out[0]=vector[0],out[1]=vector[1],out},cross=(out,a,b)=>(out[0]=0,out[1]=0,out[2]=a[0]*b[1]-a[1]*b[0],out),distance=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1];return Math.sqrt(x*x+y*y)},dot$1=(a,b)=>a[0]*b[0]+a[1]*b[1],equals$6=(a,b)=>a[0]===b[0]&&a[1]===b[1],fromAngleRadians=(out,radians)=>(out[0]=cos(radians),out[1]=sin(radians),out),fromValues$2=(x,y)=>{const out=[0,0];return out[0]=x,out[1]=y,out},max$1=(out,a,b)=>(out[0]=Math.max(a[0],b[0]),out[1]=Math.max(a[1],b[1]),out),min$1=(out,a,b)=>(out[0]=Math.min(a[0],b[0]),out[1]=Math.min(a[1],b[1]),out),negate=(out,vector)=>(out[0]=-vector[0],out[1]=-vector[1],out),rotate$1=(out,vector,origin,radians)=>{const x=vector[0]-origin[0],y=vector[1]-origin[1],c=Math.cos(radians),s=Math.sin(radians);return out[0]=x*c-y*s+origin[0],out[1]=x*s+y*c+origin[1],out},normal=(out,vector)=>rotate$1(out,vector,[0,0],TAU/4),normalize=(out,vector)=>{const x=vector[0],y=vector[1];let len=x*x+y*y;return len>0&&(len=1/Math.sqrt(len)),out[0]=x*len,out[1]=y*len,out},scale$1=(out,vector,amount)=>(out[0]=vector[0]*amount,out[1]=vector[1]*amount,out),subtract$1=(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out),toString$9=vector=>`[${vector[0].toFixed(7)}, ${vector[1].toFixed(7)}]`,transform$b=(out,vector,matrix)=>{const x=vector[0],y=vector[1];return out[0]=matrix[0]*x+matrix[4]*y+matrix[12],out[1]=matrix[1]*x+matrix[5]*y+matrix[13],out};Object.freeze({__proto__:null,abs:(out,vector)=>(out[0]=Math.abs(vector[0]),out[1]=Math.abs(vector[1]),out),add:add,angle:angleRadians,angleDegrees:angleDegrees,angleRadians:angleRadians,clone:clone$8,copy:(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out),create:()=>[0,0],cross:cross,distance:distance,divide:(out,a,b)=>(out[0]=a[0]/b[0],out[1]=a[1]/b[1],out),dot:dot$1,equals:equals$6,fromAngleDegrees:(out,degrees)=>fromAngleRadians(out,.017453292519943295*degrees),fromAngleRadians:fromAngleRadians,fromScalar:(out,scalar)=>(out[0]=scalar,out[1]=scalar,out),fromValues:fromValues$2,length:vector=>Math.sqrt(vector[0]*vector[0]+vector[1]*vector[1]),lerp:(out,a,b,t)=>{const ax=a[0],ay=a[1];return out[0]=ax+t*(b[0]-ax),out[1]=ay+t*(b[1]-ay),out},max:max$1,min:min$1,multiply:(out,a,b)=>(out[0]=a[0]*b[0],out[1]=a[1]*b[1],out),negate:negate,normal:normal,normalize:normalize,rotate:rotate$1,scale:scale$1,snap:(out,vector,epsilon)=>(out[0]=Math.round(vector[0]/epsilon)*epsilon+0,out[1]=Math.round(vector[1]/epsilon)*epsilon+0,out),squaredDistance:(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1];return x*x+y*y},squaredLength:vector=>{const x=vector[0],y=vector[1];return x*x+y*y},subtract:subtract$1,toString:toString$9,transform:transform$b});const popNextSide=(startSide,nextSides)=>{if(1===nextSides.length)return nextSides.pop();const v0=[0,0],startAngle=angleDegrees(subtract$1(v0,startSide[1],startSide[0]));let bestAngle,bestIndex;nextSides.forEach(((nextSide,index)=>{let angle=angleDegrees(subtract$1(v0,nextSide[1],nextSide[0]))-startAngle;angle<-180&&(angle+=360),angle>=180&&(angle-=360),(void 0===bestIndex||angle>bestAngle)&&(bestIndex=index,bestAngle=angle)}));const nextSide=nextSides[bestIndex];return nextSides.splice(bestIndex,1),nextSide},isA$5=object=>!!(object&&"object"==typeof object&&"outlines"in object&&"transforms"in object&&Array.isArray(object.outlines)&&"length"in object.transforms),toOutlines=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.outlines=geometry.outlines.map((outline=>outline.map((point=>transform$b([0,0],point,geometry.transforms))))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).outlines,intersect$1=(p1,p2,p3,p4,endpointTouch=!0)=>{if(p1[0]===p2[0]&&p1[1]===p2[1]||p3[0]===p4[0]&&p3[1]===p4[1])return;const denominator=(p4[1]-p3[1])*(p2[0]-p1[0])-(p4[0]-p3[0])*(p2[1]-p1[1]);if(Math.abs(denominator)<Number.MIN_VALUE)return;const ua=((p4[0]-p3[0])*(p1[1]-p3[1])-(p4[1]-p3[1])*(p1[0]-p3[0]))/denominator,ub=((p2[0]-p1[0])*(p1[1]-p3[1])-(p2[1]-p1[1])*(p1[0]-p3[0]))/denominator;return ua<0||ua>1||ub<0||ub>1||!(endpointTouch||0!==ua&&1!==ua&&0!==ub&&1!==ub)?void 0:[p1[0]+ua*(p2[0]-p1[0]),p1[1]+ua*(p2[1]-p1[1])]};Object.freeze({__proto__:null,clone:geometry=>Object.assign({},geometry),create:create$a,fromSides:sides=>{const pointMap=(sides=>{const pointMap=new Map,edges=(sides=>{const unique=new Map,getUniquePoint=point=>{const key=point.toString();return unique.has(key)?unique.get(key):(unique.set(key,point),point)};return sides.map((side=>side.map(getUniquePoint)))})(sides);return edges.forEach((edge=>{pointMap.has(edge[0])?pointMap.get(edge[0]).push(edge):pointMap.set(edge[0],[edge])})),pointMap})(sides),outlines=[];for(;;){let startSide;for(const[point,edges]of pointMap){if(startSide=edges.shift(),startSide)break;pointMap.delete(point)}if(void 0===startSide)break;const connectedPoints=[],startPoint=startSide[0];for(;;){connectedPoints.push(startSide[0]);const nextPoint=startSide[1];if(nextPoint===startPoint)break;const nextPossibleSides=pointMap.get(nextPoint);if(!nextPossibleSides)throw new Error(`geometry is not closed at point ${nextPoint}`);const nextSide=popNextSide(startSide,nextPossibleSides);0===nextPossibleSides.length&&pointMap.delete(nextPoint),startSide=nextSide}connectedPoints.length>0&&connectedPoints.push(connectedPoints.shift()),outlines.push(connectedPoints)}return pointMap.clear(),create$a(outlines)},fromCompactBinary:data=>{if(0!==data[0])throw new Error("invalid compact binary data");const created=create$a();created.transforms=clone$a(data.slice(1,17));for(let i=21;i<data.length;){const length=data[i++];if(length<0||i+2*length>data.length)throw new Error("invalid compact binary data");const outline=[];for(let j=0;j<length;j++){const x=data[i+2*j],y=data[i+2*j+1];outline.push(fromValues$2(x,y))}created.outlines.push(outline),i+=2*length}return data[17]>=0&&(created.color=[data[17],data[18],data[19],data[20]]),created},isA:isA$5,reverse:geometry=>{const outlines=toOutlines(geometry).map((outline=>outline.slice().reverse())),reversed=create$a(outlines);return geometry.color&&(reversed.color=geometry.color),reversed},toOutlines:toOutlines,toPoints:geometry=>{const points=[];return toOutlines(geometry).forEach((outline=>{outline.forEach((point=>{points.push(point)}))})),points},toSides:geometry=>{const sides=[];return toOutlines(geometry).forEach((outline=>{outline.forEach(((point,i)=>{const j=(i+1)%outline.length;sides.push([point,outline[j]])}))})),sides},toString:geometry=>{const outlines=toOutlines(geometry);let result="geom2 ("+outlines.length+" outlines):\n[\n";return outlines.forEach((outline=>{result+=" ["+outline.map(toString$9).join()+"]\n"})),result+="]\n",result},toCompactBinary:geometry=>{const transforms=geometry.transforms;let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);let size=21;geometry.outlines.forEach((outline=>{size+=2*outline.length+1}));const compacted=new Float32Array(size);compacted[0]=0,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=color[0],compacted[18]=color[1],compacted[19]=color[2],compacted[20]=color[3];let index=21;return geometry.outlines.forEach((outline=>{compacted[index++]=outline.length,outline.forEach((point=>{compacted[index++]=point[0],compacted[index++]=point[1]}))})),compacted},transform:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$5(object))throw new Error("invalid geom2 structure");if(object.outlines.forEach(((outline,i)=>{if(outline.length<3)throw new Error(`geom2 outline ${i} must contain at least 3 points`);for(let i=0;i<outline.length;i++){const j=(i+1)%outline.length;if(equals$6(outline[i],outline[j]))throw new Error(`geom2 outline ${i} has duplicate point ${outline[i]}`)}})),toOutlines(object).forEach(((outline,i)=>{for(let a1=0;a1<outline.length;a1++){const a2=(a1+1)%outline.length;for(let b1=0;b1<outline.length;b1++){const b2=(b1+1)%outline.length;if(a1!==b1){const int=intersect$1(outline[a1],outline[a2],outline[b1],outline[b2],!1);if(int)throw new Error(`geom2 outline ${i} self intersection at ${int}`)}}}})),!object.transforms.every(Number.isFinite))throw new Error(`geom2 invalid transforms ${object.transforms}`)}});const create$8=polygons=>(void 0===polygons&&(polygons=[]),{polygons:polygons,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),create$7=vertices=>((void 0===vertices||vertices.length<3)&&(vertices=[]),{vertices:vertices}),fromVerticesAndPlane=(vertices,plane)=>{const poly=create$7(vertices);return poly.plane=plane,poly},create$6=()=>[0,0,0,0],clone$5=vector=>{const out=[0,0,0,0];return out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out[3]=vector[3],out},copy$2=(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out[3]=vector[3],out),equals$5=(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3],flip=(out,plane)=>(out[0]=-plane[0],out[1]=-plane[1],out[2]=-plane[2],out[3]=-plane[3],out),fromValues$1=(x,y,z,w)=>{const out=[0,0,0,0];return out[0]=x,out[1]=y,out[2]=z,out[3]=w,out},fromPoints$4=(out,...vertices)=>{const len=vertices.length,ba=[0,0,0],ca=[0,0,0],vertexNormal=index=>{const a=vertices[index],b=vertices[(index+1)%len],c=vertices[(index+2)%len];return subtract$3(ba,b,a),subtract$3(ca,c,a),cross$1(ba,ba,ca),normalize$1(ba,ba),ba};return out[0]=0,out[1]=0,out[2]=0,3===len?copy$4(out,vertexNormal(0)):(vertices.forEach(((v,i)=>{add$1(out,out,vertexNormal(i))})),normalize$1(out,out)),out[3]=dot$2(out,vertices[0]),out},signedDistanceToPoint=(plane,point)=>dot$2(plane,point)-plane[3],toString$7=vec=>`(${vec[0].toFixed(9)}, ${vec[1].toFixed(9)}, ${vec[2].toFixed(9)}, ${vec[3].toFixed(9)})`;Object.freeze({__proto__:null,clone:clone$5,copy:copy$2,create:create$6,equals:equals$5,flip:flip,fromNormalAndPoint:(out,normal,point)=>{const u=normalize$1([0,0,0],normal),w=dot$2(point,u);return out[0]=u[0],out[1]=u[1],out[2]=u[2],out[3]=w,out},fromValues:fromValues$1,fromPoints:fromPoints$4,fromPointsRandom:(out,a,b,c)=>{let ba=subtract$3([0,0,0],b,a),ca=subtract$3([0,0,0],c,a);length$2(ba)<EPS&&(ba=orthogonal(ba,ca)),length$2(ca)<EPS&&(ca=orthogonal(ca,ba));let normal=cross$1([0,0,0],ba,ca);length$2(normal)<EPS&&(ca=orthogonal(ca,ba),normal=cross$1(normal,ba,ca)),normal=normalize$1(normal,normal);const w=dot$2(normal,a);return out[0]=normal[0],out[1]=normal[1],out[2]=normal[2],out[3]=w,out},projectionOfPoint:(plane,point)=>{const a=point[0]*plane[0]+point[1]*plane[1]+point[2]*plane[2]-plane[3],x=point[0]-a*plane[0],y=point[1]-a*plane[1],z=point[2]-a*plane[2];return fromValues$3(x,y,z)},signedDistanceToPoint:signedDistanceToPoint,toString:toString$7,transform:(out,plane,matrix)=>{const isMirror=isMirroring(matrix),r=orthogonal([0,0,0],plane),u=cross$1(r,plane,r),v=cross$1([0,0,0],plane,u);let point1=fromScalar$2([0,0,0],plane[3]);multiply$2(point1,point1,plane);let point2=add$1([0,0,0],point1,u),point3=add$1([0,0,0],point1,v);return point1=transform$c(point1,point1,matrix),point2=transform$c(point2,point2,matrix),point3=transform$c(point3,point3,matrix),fromPoints$4(out,point1,point2,point3),isMirror&&flip(out,out),out}});const invert$1=polygon=>{const vertices=polygon.vertices.slice().reverse(),inverted=create$7(vertices);return polygon.plane&&(inverted.plane=flip([0,0,0,0],polygon.plane)),inverted},isA$4=object=>!!(object&&"object"==typeof object&&"vertices"in object&&Array.isArray(object.vertices)),isConvex$1=polygon=>areVerticesConvex(polygon.vertices),areVerticesConvex=vertices=>{const numVertices=vertices.length;if(numVertices>2){const normal=fromPoints$4([0,0,0,0],...vertices);let prevPrevPos=vertices[numVertices-2],prevPos=vertices[numVertices-1];for(let i=0;i<numVertices;i++){const pos=vertices[i];if(!isConvexVertex(prevPrevPos,prevPos,pos,normal))return!1;prevPrevPos=prevPos,prevPos=pos}}return!0},isConvexVertex=(prevVertex,vertex,nextVertex,normal)=>{const crossProduct=cross$1([0,0,0],subtract$3([0,0,0],vertex,prevVertex),subtract$3([0,0,0],nextVertex,vertex));return dot$2(crossProduct,normal)>=0},plane=polygon=>(polygon.plane||(polygon.plane=fromPoints$4([0,0,0,0],...polygon.vertices)),polygon.plane),measureArea$2=polygon=>{const n=polygon.vertices.length;if(n<3)return 0;const vertices=polygon.vertices,normal=plane(polygon),ax=Math.abs(normal[0]),ay=Math.abs(normal[1]),az=Math.abs(normal[2]);if(ax+ay+az===0)return 0;let coord=3;ax>ay&&ax>az?coord=1:ay>az&&(coord=2);let area=0,h=0,i=1,j=2;switch(coord){case 1:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][1]*(vertices[j][2]-vertices[h][2]);area+=vertices[0][1]*(vertices[1][2]-vertices[n-1][2]),area/=2*normal[0];break;case 2:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][2]*(vertices[j][0]-vertices[h][0]);area+=vertices[0][2]*(vertices[1][0]-vertices[n-1][0]),area/=2*normal[1];break;default:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][0]*(vertices[j][1]-vertices[h][1]);area+=vertices[0][0]*(vertices[1][1]-vertices[n-1][1]),area/=2*normal[2]}return area};Object.freeze({__proto__:null,clone:clone$5,copy:copy$2,create:create$6,dot:(a,b)=>a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3],equals:equals$5,fromScalar:(out,scalar)=>(out[0]=scalar,out[1]=scalar,out[2]=scalar,out[3]=scalar,out),fromValues:fromValues$1,toString:toString$7,transform:(out,vector,matrix)=>{const[x,y,z,w]=vector;return out[0]=matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12]*w,out[1]=matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13]*w,out[2]=matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14]*w,out[3]=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15]*w,out}});const cache$4=new WeakMap,toVertices$1=polygon=>polygon.vertices,toString$6=polygon=>`poly3: [${polygon.vertices.map(toString$b).join(", ")}]`,transform$7=(matrix,polygon)=>{const vertices=polygon.vertices.map((vertex=>transform$c([0,0,0],vertex,matrix)));return isMirroring(matrix)&&vertices.reverse(),create$7(vertices)},validate$4=object=>{if(!isA$4(object))throw new Error("invalid poly3 structure");if(object.vertices.length<3)throw new Error(`poly3 not enough vertices ${object.vertices.length}`);if(measureArea$2(object)<=0)throw new Error("poly3 area must be greater than zero");for(let i=0;i<object.vertices.length;i++)if(equals$7(object.vertices[i],object.vertices[(i+1)%object.vertices.length]))throw new Error(`poly3 has duplicate vertex ${object.vertices[i]}`);if(!isConvex$1(object))throw new Error("poly3 must be convex");if(object.vertices.forEach((vertex=>{if(!vertex.every(Number.isFinite))throw new Error(`poly3 invalid vertex ${vertex}`)})),object.vertices.length>3){const normal=plane(object);object.vertices.forEach((vertex=>{const dist=Math.abs(signedDistanceToPoint(normal,vertex));if(dist>1e-13)throw new Error(`poly3 must be coplanar: vertex ${vertex} distance ${dist}`)}))}};Object.freeze({__proto__:null,clone:(...params)=>{let out,poly3;return 1===params.length?(out=create$7(),poly3=params[0]):(out=params[0],poly3=params[1]),out.vertices=poly3.vertices.map((vec=>clone$9(vec))),out},create:create$7,fromVerticesAndPlane:fromVerticesAndPlane,invert:invert$1,isA:isA$4,isConvex:isConvex$1,measureArea:measureArea$2,measureBoundingBox:polygon=>{const vertices=polygon.vertices,numVertices=vertices.length,min=0===numVertices?[0,0,0]:clone$9(vertices[0]),max=clone$9(min);for(let i=1;i<numVertices;i++)min$2(min,min,vertices[i]),max$2(max,max,vertices[i]);return[min,max]},measureBoundingSphere:polygon=>{const boundingSphere=cache$4.get(polygon);if(boundingSphere)return boundingSphere;const vertices=polygon.vertices,out=[0,0,0,0];if(0===vertices.length)return out[0]=0,out[1]=0,out[2]=0,out[3]=0,out;let minx=vertices[0],miny=minx,minz=minx,maxx=minx,maxy=minx,maxz=minx;vertices.forEach((v=>{minx[0]>v[0]&&(minx=v),miny[1]>v[1]&&(miny=v),minz[2]>v[2]&&(minz=v),maxx[0]<v[0]&&(maxx=v),maxy[1]<v[1]&&(maxy=v),maxz[2]<v[2]&&(maxz=v)})),out[0]=.5*(minx[0]+maxx[0]),out[1]=.5*(miny[1]+maxy[1]),out[2]=.5*(minz[2]+maxz[2]);const x=out[0]-maxx[0],y=out[1]-maxy[1],z=out[2]-maxz[2];return out[3]=Math.sqrt(x*x+y*y+z*z),cache$4.set(polygon,out),out},measureSignedVolume:polygon=>{let signedVolume=0;const vertices=polygon.vertices,cross=[0,0,0];for(let i=0;i<vertices.length-2;i++)cross$1(cross,vertices[i+1],vertices[i+2]),signedVolume+=dot$2(vertices[0],cross);return signedVolume/=6,signedVolume},plane:plane,toVertices:toVertices$1,toString:toString$6,transform:transform$7,validate:validate$4});const toPolygons$1=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.polygons=geometry.polygons.map((polygon=>transform$7(geometry.transforms,polygon))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).polygons,isA$3=object=>!!(object&&"object"==typeof object&&"polygons"in object&&"transforms"in object&&Array.isArray(object.polygons)&&"length"in object.transforms);Object.freeze({__proto__:null,clone:geometry=>Object.assign({},geometry),create:create$8,fromPoints:listOfLists=>{if(!Array.isArray(listOfLists))throw new Error("the given vertices must be an array");return create$8(listOfLists.map(create$7))},fromCompactBinary:data=>{if(1!==data[0])throw new Error("invalid compact binary data");const created=create$8();created.transforms=clone$a(data.slice(1,17));const numberOfVertices=data[21];let ci=22,vi=data.length-3*numberOfVertices;for(;vi<data.length;){const verticesPerPolygon=data[ci];ci++;const vertices=[];for(let i=0;i<verticesPerPolygon;i++)vertices.push(fromValues$3(data[vi],data[vi+1],data[vi+2])),vi+=3;created.polygons.push(create$7(vertices))}return data[17]>=0&&(created.color=[data[17],data[18],data[19],data[20]]),created},invert:geometry=>{const newPolygons=toPolygons$1(geometry).map((polygon=>invert$1(polygon)));return create$8(newPolygons)},isA:isA$3,toPoints:geometry=>toPolygons$1(geometry).map((polygon=>toVertices$1(polygon))),toPolygons:toPolygons$1,toString:geometry=>{const polygons=toPolygons$1(geometry);let result="geom3 ("+polygons.length+" polygons):\n";return polygons.forEach((polygon=>{result+=" "+toString$6(polygon)+"\n"})),result},toCompactBinary:geometry=>{const polygons=geometry.polygons,transforms=geometry.transforms,numberOfPolygons=polygons.length,numberOfVertices=polygons.reduce(((count,polygon)=>count+polygon.vertices.length),0);let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);const compacted=new Float32Array(22+numberOfPolygons+3*numberOfVertices);compacted[0]=1,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=color[0],compacted[18]=color[1],compacted[19]=color[2],compacted[20]=color[3],compacted[21]=numberOfVertices;let ci=22,vi=ci+numberOfPolygons;return polygons.forEach((polygon=>{const vertices=toVertices$1(polygon);compacted[ci]=vertices.length,ci++;for(let i=0;i<vertices.length;i++){const vertex=vertices[i];compacted[vi+0]=vertex[0],compacted[vi+1]=vertex[1],compacted[vi+2]=vertex[2],vi+=3}})),compacted},transform:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$3(object))throw new Error("invalid geom3 structure");if(object.polygons.forEach(validate$4),(object=>{const edgeCount=new Map;object.polygons.forEach((({vertices:vertices})=>{vertices.forEach(((v,i)=>{const edge=`${v}/${vertices[(i+1)%vertices.length]}`,count=edgeCount.has(edge)?edgeCount.get(edge):0;edgeCount.set(edge,count+1)}))}));const nonManifold=[];if(edgeCount.forEach(((count,edge)=>{const complementEdge=edge.split("/").reverse().join("/");count!==edgeCount.get(complementEdge)&&nonManifold.push(edge.replace("/"," -> "))})),nonManifold.length>0)throw new Error(`non-manifold edges ${nonManifold.length}\n${nonManifold.join("\n")}`)})(object),!object.transforms.every(Number.isFinite))throw new Error(`geom3 invalid transforms ${object.transforms}`)}});const clone$4=geometry=>Object.assign({},geometry),close=geometry=>{if(geometry.isClosed)return geometry;const cloned=clone$4(geometry);if(cloned.isClosed=!0,cloned.points.length>1){const points=cloned.points,p0=points[0];let pn=points[points.length-1];for(;distance(p0,pn)<EPS*EPS&&(points.pop(),1!==points.length);)pn=points[points.length-1]}return cloned},create$5=points=>(void 0===points&&(points=[]),{points:points,isClosed:!1,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),fromPoints$2=(options,points)=>{let{closed:closed}=Object.assign({},{closed:!1},options),created=create$5();if(created.points=points.map((point=>clone$8(point))),created.points.length>1){const p0=created.points[0],pn=created.points[created.points.length-1];distance(p0,pn)<EPS*EPS&&(closed=!0)}return!0===closed&&(created=close(created)),created},toPoints$1=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.points=geometry.points.map((point=>transform$b([0,0],point,geometry.transforms))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).points,concat=(...paths)=>{let isClosed=!1,newPoints=[];return paths.forEach(((path,i)=>{const tmp=toPoints$1(path).slice();if(newPoints.length>0&&tmp.length>0&&equals$6(tmp[0],newPoints[newPoints.length-1])&&tmp.shift(),tmp.length>0&&isClosed)throw new Error(`Cannot concatenate to a closed path; check the ${i}th path`);isClosed=path.isClosed,newPoints=newPoints.concat(tmp)})),fromPoints$2({closed:isClosed},newPoints)},appendPoints=(points,geometry)=>concat(geometry,create$5(points)),isA$2=object=>!!(object&&"object"==typeof object&&"points"in object&&"transforms"in object&&"isClosed"in object&&Array.isArray(object.points)&&"length"in object.transforms);Object.freeze({__proto__:null,appendArc:(options,geometry)=>{let{endpoint:endpoint,radius:radius,xaxisRotation:xaxisRotation,clockwise:clockwise,large:large,segments:segments}=Object.assign({},{radius:[0,0],xaxisRotation:0,clockwise:!1,large:!1,segments:16},options);if(!Array.isArray(endpoint))throw new Error("endpoint must be an array of X and Y values");if(endpoint.length<2)throw new Error("endpoint must contain X and Y values");if(endpoint=clone$8(endpoint),!Array.isArray(radius))throw new Error("radius must be an array of X and Y values");if(radius.length<2)throw new Error("radius must contain X and Y values");if(segments<4)throw new Error("segments must be four or more");if(geometry.isClosed)throw new Error("the given path cannot be closed");const points=toPoints$1(geometry);if(points.length<1)throw new Error("the given path must contain one or more points (as the starting point for the arc)");let xRadius=radius[0],yRadius=radius[1];const startpoint=points[points.length-1];xRadius=Math.round(1e5*xRadius)/1e5,yRadius=Math.round(1e5*yRadius)/1e5,endpoint=fromValues$2(Math.round(1e5*endpoint[0])/1e5,Math.round(1e5*endpoint[1])/1e5);const sweepFlag=!clockwise;let newPoints=[];if(0===xRadius||0===yRadius)newPoints.push(endpoint);else{xRadius=Math.abs(xRadius),yRadius=Math.abs(yRadius);const phi=xaxisRotation,cosPhi=Math.cos(phi),sinPhi=Math.sin(phi),minusHalfDistance=subtract$1([0,0],startpoint,endpoint);scale$1(minusHalfDistance,minusHalfDistance,.5);const x=Math.round(1e5*(cosPhi*minusHalfDistance[0]+sinPhi*minusHalfDistance[1]))/1e5,y=Math.round(1e5*(-sinPhi*minusHalfDistance[0]+cosPhi*minusHalfDistance[1]))/1e5,startTranslated=fromValues$2(x,y),bigLambda=startTranslated[0]*startTranslated[0]/(xRadius*xRadius)+startTranslated[1]*startTranslated[1]/(yRadius*yRadius);if(bigLambda>1){const sqrtBigLambda=Math.sqrt(bigLambda);xRadius*=sqrtBigLambda,yRadius*=sqrtBigLambda,xRadius=Math.round(1e5*xRadius)/1e5,yRadius=Math.round(1e5*yRadius)/1e5}let multiplier1=Math.sqrt((xRadius*xRadius*yRadius*yRadius-xRadius*xRadius*startTranslated[1]*startTranslated[1]-yRadius*yRadius*startTranslated[0]*startTranslated[0])/(xRadius*xRadius*startTranslated[1]*startTranslated[1]+yRadius*yRadius*startTranslated[0]*startTranslated[0]));sweepFlag===large&&(multiplier1=-multiplier1);const centerTranslated=fromValues$2(xRadius*startTranslated[1]/yRadius,-yRadius*startTranslated[0]/xRadius);scale$1(centerTranslated,centerTranslated,multiplier1);let center=fromValues$2(cosPhi*centerTranslated[0]-sinPhi*centerTranslated[1],sinPhi*centerTranslated[0]+cosPhi*centerTranslated[1]);center=add(center,center,scale$1([0,0],add([0,0],startpoint,endpoint),.5));const vector1=fromValues$2((startTranslated[0]-centerTranslated[0])/xRadius,(startTranslated[1]-centerTranslated[1])/yRadius),vector2=fromValues$2((-startTranslated[0]-centerTranslated[0])/xRadius,(-startTranslated[1]-centerTranslated[1])/yRadius),theta1=angleRadians(vector1);let deltatheta=angleRadians(vector2)-theta1;deltatheta%=TAU,!sweepFlag&&deltatheta>0?deltatheta-=TAU:sweepFlag&&deltatheta<0&&(deltatheta+=TAU);let numSteps=Math.ceil(Math.abs(deltatheta)/TAU*segments)+1;numSteps<1&&(numSteps=1);for(let step=1;step<numSteps;step++){const theta=theta1+step/numSteps*deltatheta,cosTheta=Math.cos(theta),sinTheta=Math.sin(theta),point=fromValues$2(cosPhi*xRadius*cosTheta-sinPhi*yRadius*sinTheta,sinPhi*xRadius*cosTheta+cosPhi*yRadius*sinTheta);add(point,point,center),newPoints.push(point)}numSteps&&newPoints.push(options.endpoint)}return newPoints=points.concat(newPoints),fromPoints$2({},newPoints)},appendBezier:(options,geometry)=>{let{controlPoints:controlPoints,segments:segments}=Object.assign({},{segments:16},options);if(!Array.isArray(controlPoints))throw new Error("controlPoints must be an array of one or more points");if(controlPoints.length<1)throw new Error("controlPoints must be an array of one or more points");if(segments<4)throw new Error("segments must be four or more");if(geometry.isClosed)throw new Error("the given geometry cannot be closed");const points=toPoints$1(geometry);if(points.length<1)throw new Error("the given path must contain one or more points (as the starting point for the bezier curve)");if(controlPoints=controlPoints.slice(),null===controlPoints[0]){if(controlPoints.length<2)throw new Error("a null control point must be passed with one more control points");let lastBezierControlPoint=points[points.length-2];if("lastBezierControlPoint"in geometry&&(lastBezierControlPoint=geometry.lastBezierControlPoint),!Array.isArray(lastBezierControlPoint))throw new Error("the given path must contain TWO or more points if given a null control point");const controlPoint=scale$1([0,0],points[points.length-1],2);subtract$1(controlPoint,controlPoint,lastBezierControlPoint),controlPoints[0]=controlPoint}controlPoints.unshift(points[points.length-1]);const bezierOrder=controlPoints.length-1,factorials=[];let fact=1;for(let i=0;i<=bezierOrder;++i)i>0&&(fact*=i),factorials.push(fact);const binomials=[];for(let i=0;i<=bezierOrder;++i){const binomial=factorials[bezierOrder]/(factorials[i]*factorials[bezierOrder-i]);binomials.push(binomial)}const v0=[0,0],v1=[0,0],v3=[0,0,0],getPointForT=t=>{let tk=1,oneMinusTNMinusK=Math.pow(1-t,bezierOrder);const invOneMinusT=1!==t?1/(1-t):1,point=[0,0];for(let k=0;k<=bezierOrder;++k){k===bezierOrder&&(oneMinusTNMinusK=1);const bernsteinCoefficient=binomials[k]*tk*oneMinusTNMinusK,derivativePoint=scale$1(v0,controlPoints[k],bernsteinCoefficient);add(point,point,derivativePoint),tk*=t,oneMinusTNMinusK*=invOneMinusT}return point},newPoints=[],newPointsT=[],numSteps=bezierOrder+1;for(let i=0;i<numSteps;++i){const t=i/(numSteps-1),point=getPointForT(t);newPoints.push(point),newPointsT.push(t)}let subdivideBase=1;const maxAngle=TAU/segments,maxSinAngle=Math.sin(maxAngle);for(;subdivideBase<newPoints.length-1;){const dir1=subtract$1(v0,newPoints[subdivideBase],newPoints[subdivideBase-1]);normalize(dir1,dir1);const dir2=subtract$1(v1,newPoints[subdivideBase+1],newPoints[subdivideBase]);normalize(dir2,dir2);const sinAngle=cross(v3,dir1,dir2);if(Math.abs(sinAngle[2])>maxSinAngle){const t0=newPointsT[subdivideBase-1],t1=newPointsT[subdivideBase+1],newt0=t0+1*(t1-t0)/3,newt1=t0+2*(t1-t0)/3,point0=getPointForT(newt0),point1=getPointForT(newt1);newPoints.splice(subdivideBase,1,point0,point1),newPointsT.splice(subdivideBase,1,newt0,newt1),subdivideBase--,subdivideBase<1&&(subdivideBase=1)}else++subdivideBase}newPoints.shift();const result=appendPoints(newPoints,geometry);return result.lastBezierControlPoint=controlPoints[controlPoints.length-2],result},appendPoints:appendPoints,clone:clone$4,close:close,concat:concat,create:create$5,equals:(a,b)=>{if(a.isClosed!==b.isClosed)return!1;if(a.points.length!==b.points.length)return!1;const aPoints=toPoints$1(a),bPoints=toPoints$1(b),length=aPoints.length;let offset=0;do{let unequal=!1;for(let i=0;i<length;i++)if(!equals$6(aPoints[i],bPoints[(i+offset)%length])){unequal=!0;break}if(!1===unequal)return!0;if(!a.isClosed)return!1}while(++offset<length);return!1},fromPoints:fromPoints$2,fromCompactBinary:data=>{if(2!==data[0])throw new Error("invalid compact binary data");const created=create$5();created.transforms=clone$a(data.slice(1,17)),created.isClosed=!!data[17];for(let i=22;i<data.length;i+=2){const point=fromValues$2(data[i],data[i+1]);created.points.push(point)}return data[18]>=0&&(created.color=[data[18],data[19],data[20],data[21]]),created},isA:isA$2,reverse:geometry=>{const cloned=clone$4(geometry);return cloned.points=geometry.points.slice().reverse(),cloned},toPoints:toPoints$1,toString:geometry=>{const points=toPoints$1(geometry);let result="path ("+points.length+" points, "+geometry.isClosed+"):\n[\n";return points.forEach((point=>{result+=" "+toString$9(point)+",\n"})),result+="]\n",result},toCompactBinary:geometry=>{const points=geometry.points,transforms=geometry.transforms;let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);const compacted=new Float32Array(22+2*points.length);compacted[0]=2,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=geometry.isClosed?1:0,compacted[18]=color[0],compacted[19]=color[1],compacted[20]=color[2],compacted[21]=color[3];for(let j=0;j<points.length;j++){const ci=2*j+22,point=points[j];compacted[ci]=point[0],compacted[ci+1]=point[1]}return compacted},transform:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$2(object))throw new Error("invalid path2 structure");if(object.points.length>1)for(let i=0;i<object.points.length;i++)if(equals$6(object.points[i],object.points[(i+1)%object.points.length]))throw new Error(`path2 has duplicate point ${object.points[i]}`);if(object.points.forEach((point=>{if(!point.every(Number.isFinite))throw new Error(`path2 invalid point ${point}`)})),!object.transforms.every(Number.isFinite))throw new Error(`path2 invalid transforms ${object.transforms}`)}});const getPermutations=function(c){const permutations=[];for(let i=0;i<=c;i++)permutations.push(factorial(c)/(factorial(i)*factorial(c-i)));return permutations},factorial=function(b){let out=1;for(let i=2;i<=b;i++)out*=i;return out},valueAt=(t,bezier)=>{if(t<0||t>1)throw new Error("Bezier valueAt() input must be between 0 and 1");if("float_single"===bezier.pointType)return bezierFunction(bezier,bezier.points,t);{const result=[];for(let i=0;i<bezier.dimensions;i++){const singleDimensionPoints=[];for(let j=0;j<bezier.points.length;j++)singleDimensionPoints.push(bezier.points[j][i]);result.push(bezierFunction(bezier,singleDimensionPoints,t))}return result}},bezierFunction=function(bezier,p,t){const n=p.length-1;let result=0;for(let i=0;i<=n;i++)result+=bezier.permutations[i]*Math.pow(1-t,n-i)*Math.pow(t,i)*p[i];return result},bezierTangent=function(bezier,p,t){const n=p.length-1;let result=0;for(let i=0;i<n;i++){const q=n*(p[i+1]-p[i]);result+=bezier.tangentPermutations[i]*Math.pow(1-t,n-1-i)*Math.pow(t,i)*q}return result},lengths=(segments,bezier)=>{let sum=0;const lengths=[0];let previous=valueAt(0,bezier);for(let index=1;index<=segments;index++){const current=valueAt(index/segments,bezier);sum+=distanceBetween(current,previous),lengths.push(sum),previous=current}return lengths},distanceBetween=(a,b)=>{if(Number.isFinite(a)&&Number.isFinite(b))return Math.abs(a-b);if(Array.isArray(a)&&Array.isArray(b)){if(a.length!==b.length)throw new Error("The operands must have the same number of dimensions.");let sum=0;for(let i=0;i<a.length;i++)sum+=(b[i]-a[i])*(b[i]-a[i]);return Math.sqrt(sum)}throw new Error("The operands must be of the same type, either number or array.")};Object.freeze({__proto__:null,create:points=>{if(!Array.isArray(points))throw new Error("Bezier points must be a valid array/");if(points.length<2)throw new Error("Bezier points must contain at least 2 values.");const pointType=function(points){let firstPointType=null;return points.forEach((point=>{let pType="";if(Number.isFinite(point))pType="float_single";else{if(!Array.isArray(point))throw new Error("Bezier points must all be numbers or arrays of number.");point.forEach((val=>{if(!Number.isFinite(val))throw new Error("Bezier point values must all be numbers.")})),pType="float_"+point.length}if(null==firstPointType)firstPointType=pType;else if(firstPointType!==pType)throw new Error("Bezier points must be either all numbers or all arrays of numbers of the same size.")})),firstPointType}(points);return{points:points,pointType:pointType,dimensions:"float_single"===pointType?0:points[0].length,permutations:getPermutations(points.length-1),tangentPermutations:getPermutations(points.length-2)}},valueAt:valueAt,tangentAt:(t,bezier)=>{if(t<0||t>1)throw new Error("Bezier tangentAt() input must be between 0 and 1");if("float_single"===bezier.pointType)return bezierTangent(bezier,bezier.points,t);{const result=[];for(let i=0;i<bezier.dimensions;i++){const singleDimensionPoints=[];for(let j=0;j<bezier.points.length;j++)singleDimensionPoints.push(bezier.points[j][i]);result.push(bezierTangent(bezier,singleDimensionPoints,t))}return result}},lengths:lengths,length:(segments,bezier)=>lengths(segments,bezier)[segments],arcLengthToT:(options,bezier)=>{const{distance:distance,segments:segments}=Object.assign({},{distance:0,segments:100},options),arcLengths=lengths(segments,bezier);let startIndex=0,endIndex=segments;for(;startIndex<=endIndex;){const middleIndex=Math.floor(startIndex+(endIndex-startIndex)/2),diff=arcLengths[middleIndex]-distance;if(diff<0)startIndex=middleIndex+1;else{if(!(diff>0)){endIndex=middleIndex;break}endIndex=middleIndex-1}}const targetIndex=endIndex;if(arcLengths[targetIndex]===distance)return targetIndex/segments;const lengthBefore=arcLengths[targetIndex];return(targetIndex+(distance-lengthBefore)/(arcLengths[targetIndex+1]-lengthBefore))/segments}});const area$1=points=>{let area=0;for(let i=0;i<points.length;i++){const j=(i+1)%points.length;area+=points[i][0]*points[j][1],area-=points[j][0]*points[i][1]}return area/2},measureArea$1=polygon=>area$1(polygon.points),create$3=points=>((void 0===points||points.length<3)&&(points=[]),{points:points}),reverse$3=polygon=>{const points=polygon.points.slice().reverse();return create$3(points)},arePointsInside=(points,polygon)=>0===points.length||polygon.points.length<3?0:(measureArea$1(polygon)<0&&(polygon=reverse$3(polygon)),points.reduce(((acc,point)=>acc+isPointInside(point,polygon.points)),0)===points.length?1:0),isPointInside=(point,polygon)=>{const numPoints=polygon.length,tx=point[0],ty=point[1];let vtx0=polygon[numPoints-1],vtx1=polygon[0],yFlag0=vtx0[1]>ty,insideFlag=0,i=0;for(let j=numPoints+1;--j;){const yFlag1=vtx1[1]>ty;if(yFlag0!==yFlag1){const xFlag0=vtx0[0]>tx,xFlag1=vtx1[0]>tx;(xFlag0&&xFlag1||vtx1[0]-(vtx1[1]-ty)*(vtx0[0]-vtx1[0])/(vtx0[1]-vtx1[1])>=tx)&&(insideFlag=!insideFlag)}yFlag0=yFlag1,vtx0=vtx1,vtx1=polygon[++i]}return insideFlag},isA$1=object=>!!(object&&"object"==typeof object&&"points"in object&&Array.isArray(object.points)),crossBetweenSegments=(p1,p2,p3)=>{const X1=p2[0]-p1[0],Y1=p2[1]-p1[1],X2=p3[0]-p1[0];return X1*(p3[1]-p1[1])-Y1*X2};Object.freeze({__proto__:null,arePointsInside:arePointsInside,clone:polygon=>Object.assign({},polygon),create:create$3,isA:isA$1,isConvex:polygon=>{const numPoints=polygon.points.length;if(numPoints>2){const points=polygon.points;let prev=0,curr=0;for(let i=0;i<numPoints;i++)if(curr=crossBetweenSegments(points[i],points[(i+1)%numPoints],points[(i+2)%numPoints]),0!==curr){if(curr*prev<0)return!1;prev=curr}}return!0},isSimple:polygon=>{const numPoints=polygon.points.length;if(numPoints<3)return!1;if(3===numPoints)return!0;const points=polygon.points,found=new Set;if(points.forEach((v=>found.add(v.toString()))),found.size!==numPoints)return!1;for(let i=0;i<numPoints;i++)for(let j=i+2;j<numPoints;j++){const k=(j+1)%numPoints;if(i!==k){const s0=points[i],s1=points[(i+1)%numPoints],z0=points[j],z1=points[k];if(intersect$1(s0,s1,z0,z1))return!1}}return!0},measureArea:measureArea$1,measureBoundingBox:polygon=>{const points=polygon.points,numPoints=points.length,min=0===numPoints?[0,0]:clone$8(points[0]),max=clone$8(min);for(let i=1;i<numPoints;i++)min$1(min,min,points[i]),max$1(max,max,points[i]);return[min,max]},reverse:reverse$3,toPoints:polygon=>polygon.points,toString:polygon=>`poly2: [${polygon.points.map(toString$9).join(", ")}]`,transform:(matrix,polygon)=>{const points=polygon.points.map((point=>transform$b([0,0],point,matrix)));return isMirroring(matrix)&&points.reverse(),create$3(points)},validate:object=>{if(!isA$1(object))throw new Error("invalid poly2 structure");if(object.points.length<3)throw new Error(`poly2 not enough points ${object.points.length}`);if(measureArea$1(object)<=0)throw new Error("poly2 area must be greater than zero");for(let i=0;i<object.points.length;i++)if(equals$6(object.points[i],object.points[(i+1)%object.points.length]))throw new Error(`poly2 duplicate point at ${i}: [${object.points[i]}]`);object.points.forEach((point=>{if(2!==point.length)throw new Error(`poly2 invalid point ${point}`);if(!point.every(Number.isFinite))throw new Error(`poly2 invalid point ${point}`)}))}});const calculatePlane=slice=>{if(slice.contours.length<1)throw new Error("slices must have at least one contour to calculate a plane");const middle=[0,0,0];let n=0;slice.contours.forEach((contour=>{contour.forEach((vertex=>{add$1(middle,middle,vertex),n++}))})),scale$3(middle,middle,1/n);let farthestBefore,farthestVertex,farthestAfter,farthestContour=[],distance=0;slice.contours.forEach((contour=>{let prev=contour[contour.length-1];contour.forEach((vertex=>{if(!equals$7(prev,vertex)){const d=squaredDistance$1(middle,vertex);d>distance&&(farthestContour=contour,farthestBefore=prev,farthestVertex=vertex,distance=d)}prev=vertex}))}));let prev=farthestContour[farthestContour.length-1];for(let i=0;i<farthestContour.length;i++){const vertex=farthestContour[i];if(!equals$7(prev,vertex)&&equals$7(prev,farthestVertex)){farthestAfter=vertex;break}prev=vertex}return fromPoints$4([0,0,0,0],farthestBefore,farthestVertex,farthestAfter)},create$2=(contours=[])=>({contours:contours}),isA=object=>!!(object&&"object"==typeof object&&"contours"in object&&Array.isArray(object.contours));class Node$2{constructor(i,x,y){this.i=i,this.x=x,this.y=y,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}}const insertNode=(i,x,y,last)=>{const p=new Node$2(i,x,y);return last?(p.next=last.next,p.prev=last,last.next.prev=p,last.next=p):(p.prev=p,p.next=p),p},removeNode=p=>{p.next.prev=p.prev,p.prev.next=p.next,p.prevZ&&(p.prevZ.nextZ=p.nextZ),p.nextZ&&(p.nextZ.prevZ=p.prevZ)},pointInTriangle=(ax,ay,bx,by,cx,cy,px,py)=>(cx-px)*(ay-py)-(ax-px)*(cy-py)>=0&&(ax-px)*(by-py)-(bx-px)*(ay-py)>=0&&(bx-px)*(cy-py)-(cx-px)*(by-py)>=0,area=(p,q,r)=>(q.y-p.y)*(r.x-q.x)-(q.x-p.x)*(r.y-q.y),linkedPolygon=(data,start,end,dim,clockwise)=>{let last;if(clockwise===signedArea$1(data,start,end,dim)>0)for(let i=start;i<end;i+=dim)last=insertNode(i,data[i],data[i+1],last);else for(let i=end-dim;i>=start;i-=dim)last=insertNode(i,data[i],data[i+1],last);return last&&equals$2(last,last.next)&&(removeNode(last),last=last.next),last},filterPoints=(start,end)=>{if(!start)return start;end||(end=start);let again,p=start;do{if(again=!1,p.steiner||!equals$2(p,p.next)&&0!==area(p.prev,p,p.next))p=p.next;else{if(removeNode(p),p=end=p.prev,p===p.next)break;again=!0}}while(again||p!==end);return end},cureLocalIntersections=(start,triangles,dim)=>{let p=start;do{const a=p.prev,b=p.next.next;!equals$2(a,b)&&intersects(a,p,p.next,b)&&locallyInside(a,b)&&locallyInside(b,a)&&(triangles.push(a.i/dim),triangles.push(p.i/dim),triangles.push(b.i/dim),removeNode(p),removeNode(p.next),p=start=b),p=p.next}while(p!==start);return filterPoints(p)},locallyInside=(a,b)=>area(a.prev,a,a.next)<0?area(a,b,a.next)>=0&&area(a,a.prev,b)>=0:area(a,b,a.prev)<0||area(a,a.next,b)<0,splitPolygon=(a,b)=>{const a2=new Node$2(a.i,a.x,a.y),b2=new Node$2(b.i,b.x,b.y),an=a.next,bp=b.prev;return a.next=b,b.prev=a,a2.next=an,an.prev=a2,b2.next=a2,a2.prev=b2,bp.next=b2,b2.prev=bp,b2},isValidDiagonal=(a,b)=>a.next.i!==b.i&&a.prev.i!==b.i&&!((a,b)=>{let p=a;do{if(p.i!==a.i&&p.next.i!==a.i&&p.i!==b.i&&p.next.i!==b.i&&intersects(p,p.next,a,b))return!0;p=p.next}while(p!==a);return!1})(a,b)&&(locallyInside(a,b)&&locallyInside(b,a)&&((a,b)=>{let p=a,inside=!1;const px=(a.x+b.x)/2,py=(a.y+b.y)/2;do{p.y>py!=p.next.y>py&&p.next.y!==p.y&&px<(p.next.x-p.x)*(py-p.y)/(p.next.y-p.y)+p.x&&(inside=!inside),p=p.next}while(p!==a);return inside})(a,b)&&(area(a.prev,a,b.prev)||area(a,b.prev,b))||equals$2(a,b)&&area(a.prev,a,a.next)>0&&area(b.prev,b,b.next)>0),intersects=(p1,q1,p2,q2)=>{const o1=Math.sign(area(p1,q1,p2)),o2=Math.sign(area(p1,q1,q2)),o3=Math.sign(area(p2,q2,p1)),o4=Math.sign(area(p2,q2,q1));return o1!==o2&&o3!==o4||!(0!==o1||!onSegment(p1,p2,q1))||!(0!==o2||!onSegment(p1,q2,q1))||!(0!==o3||!onSegment(p2,p1,q2))||!(0!==o4||!onSegment(p2,q1,q2))},onSegment=(p,q,r)=>q.x<=Math.max(p.x,r.x)&&q.x>=Math.min(p.x,r.x)&&q.y<=Math.max(p.y,r.y)&&q.y>=Math.min(p.y,r.y),signedArea$1=(data,start,end,dim)=>{let sum=0;for(let i=start,j=end-dim;i<end;i+=dim)sum+=(data[j]-data[i])*(data[i+1]+data[j+1]),j=i;return sum},equals$2=(p1,p2)=>p1.x===p2.x&&p1.y===p2.y,eliminateHole=(hole,outerNode)=>{const bridge=findHoleBridge(hole,outerNode);if(!bridge)return outerNode;const bridgeReverse=splitPolygon(bridge,hole),filteredBridge=filterPoints(bridge,bridge.next);return filterPoints(bridgeReverse,bridgeReverse.next),outerNode===bridge?filteredBridge:outerNode},findHoleBridge=(hole,outerNode)=>{let p=outerNode;const hx=hole.x,hy=hole.y;let m,qx=-1/0;do{if(hy<=p.y&&hy>=p.next.y&&p.next.y!==p.y){const x=p.x+(hy-p.y)*(p.next.x-p.x)/(p.next.y-p.y);if(x<=hx&&x>qx){if(qx=x,x===hx){if(hy===p.y)return p;if(hy===p.next.y)return p.next}m=p.x<p.next.x?p:p.next}}p=p.next}while(p!==outerNode);if(!m)return null;if(hx===qx)return m;const stop=m,mx=m.x,my=m.y;let tanMin=1/0;p=m;do{if(hx>=p.x&&p.x>=mx&&hx!==p.x&&pointInTriangle(hy<my?hx:qx,hy,mx,my,hy<my?qx:hx,hy,p.x,p.y)){const tan=Math.abs(hy-p.y)/(hx-p.x);locallyInside(p,hole)&&(tan<tanMin||tan===tanMin&&(p.x>m.x||p.x===m.x&&sectorContainsSector(m,p)))&&(m=p,tanMin=tan)}p=p.next}while(p!==stop);return m},sectorContainsSector=(m,p)=>area(m.prev,m,p.prev)<0&&area(p.next,m,m.next)<0,getLeftmost=start=>{let p=start,leftmost=start;do{(p.x<leftmost.x||p.x===leftmost.x&&p.y<leftmost.y)&&(leftmost=p),p=p.next}while(p!==start);return leftmost},earcutLinked=(ear,triangles,dim,minX,minY,invSize,pass)=>{if(!ear)return;!pass&&invSize&&indexCurve(ear,minX,minY,invSize);let prev,next,stop=ear;for(;ear.prev!==ear.next;)if(prev=ear.prev,next=ear.next,invSize?isEarHashed(ear,minX,minY,invSize):isEar(ear))triangles.push(prev.i/dim),triangles.push(ear.i/dim),triangles.push(next.i/dim),removeNode(ear),ear=next.next,stop=next.next;else if((ear=next)===stop){pass?1===pass?(ear=cureLocalIntersections(filterPoints(ear),triangles,dim),earcutLinked(ear,triangles,dim,minX,minY,invSize,2)):2===pass&&splitEarcut(ear,triangles,dim,minX,minY,invSize):earcutLinked(filterPoints(ear),triangles,dim,minX,minY,invSize,1);break}},isEar=ear=>{const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;let p=ear.next.next;for(;p!==ear.prev;){if(pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.next}return!0},isEarHashed=(ear,minX,minY,invSize)=>{const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;const minTX=a.x<b.x?a.x<c.x?a.x:c.x:b.x<c.x?b.x:c.x,minTY=a.y<b.y?a.y<c.y?a.y:c.y:b.y<c.y?b.y:c.y,maxTX=a.x>b.x?a.x>c.x?a.x:c.x:b.x>c.x?b.x:c.x,maxTY=a.y>b.y?a.y>c.y?a.y:c.y:b.y>c.y?b.y:c.y,minZ=zOrder(minTX,minTY,minX,minY,invSize),maxZ=zOrder(maxTX,maxTY,minX,minY,invSize);let p=ear.prevZ,n=ear.nextZ;for(;p&&p.z>=minZ&&n&&n.z<=maxZ;){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}for(;p&&p.z>=minZ;){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;n&&n.z<=maxZ;){if(n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}return!0},splitEarcut=(start,triangles,dim,minX,minY,invSize)=>{let a=start;do{let b=a.next.next;for(;b!==a.prev;){if(a.i!==b.i&&isValidDiagonal(a,b)){let c=splitPolygon(a,b);return a=filterPoints(a,a.next),c=filterPoints(c,c.next),earcutLinked(a,triangles,dim,minX,minY,invSize),void earcutLinked(c,triangles,dim,minX,minY,invSize)}b=b.next}a=a.next}while(a!==start)},indexCurve=(start,minX,minY,invSize)=>{let p=start;do{null===p.z&&(p.z=zOrder(p.x,p.y,minX,minY,invSize)),p.prevZ=p.prev,p.nextZ=p.next,p=p.next}while(p!==start);p.prevZ.nextZ=null,p.prevZ=null,((list,fn)=>{let i,p,q,e,numMerges,inSize=1;do{p=list,list=null;let tail=null;for(numMerges=0;p;){numMerges++,q=p;let pSize=0;for(i=0;i<inSize&&(pSize++,q=q.nextZ,q);i++);let qSize=inSize;for(;pSize>0||qSize>0&&q;)0!==pSize&&(0===qSize||!q||fn(p)<=fn(q))?(e=p,p=p.nextZ,pSize--):(e=q,q=q.nextZ,qSize--),tail?tail.nextZ=e:list=e,e.prevZ=tail,tail=e;p=q}tail.nextZ=null,inSize*=2}while(numMerges>1)})(p,(p=>p.z))},zOrder=(x,y,minX,minY,invSize)=>(x=1431655765&((x=858993459&((x=252645135&((x=16711935&((x=32767*(x-minX)*invSize)|x<<8))|x<<4))|x<<2))|x<<1))|(y=1431655765&((y=858993459&((y=252645135&((y=16711935&((y=32767*(y-minY)*invSize)|y<<8))|y<<4))|y<<2))|y<<1))<<1;class PolygonHierarchy{constructor(slice){this.plane=calculatePlane(slice);const rightVector=orthogonal([0,0,0],this.plane),perp=cross$1([0,0,0],this.plane,rightVector);this.v=normalize$1(perp,perp),this.u=cross$1([0,0,0],this.v,this.plane),this.basisMap=new Map;const projected=slice.contours.map((part=>part.map((v=>this.to2D(v))))),geometry=create$a(projected);this.roots=(geometry=>{const outlines=toOutlines(geometry),solids=[],holes=[];outlines.forEach(((outline,i)=>{const a=area$1(outline);a<0?holes.push(i):a>0&&solids.push(i)}));const children=[],parents=[];return solids.forEach(((s,i)=>{const solid=outlines[s];children[i]=[],holes.forEach(((h,j)=>{const hole=outlines[h];arePointsInside([hole[0]],create$3(solid))&&(children[i].push(h),parents[j]||(parents[j]=[]),parents[j].push(i))}))})),holes.forEach(((h,j)=>{if(parents[j]&&parents[j].length>1){const directParent=((list,score)=>{let bestIndex,best;return list.forEach(((item,index)=>{const value=score(item);(void 0===best||value<best)&&(bestIndex=index,best=value)})),bestIndex})(parents[j],(p=>children[p].length));parents[j].forEach(((p,i)=>{i!==directParent&&(children[p]=children[p].filter((c=>c!==h)))}))}})),children.map(((holes,i)=>({solid:outlines[solids[i]],holes:holes.map((h=>outlines[h]))})))})(geometry)}to2D(vector3){const vector2=fromValues$2(dot$2(vector3,this.u),dot$2(vector3,this.v));return this.basisMap.set(vector2,vector3),vector2}to3D(vector2){const original=this.basisMap.get(vector2);if(original)return original;{console.log("Warning: point not in original slice");const v1=scale$3([0,0,0],this.u,vector2[0]),v2=scale$3([0,0,0],this.v,vector2[1]),planeOrigin=scale$3([0,0,0],this.plane,this.plane[3]),v3=add$1(v1,v1,planeOrigin);return add$1(v2,v2,v3)}}}Object.freeze({__proto__:null,calculatePlane:calculatePlane,clone:slice=>Object.assign({},slice),create:create$2,equals:(a,b)=>{if(a.contours.length!==b.contours.length)return!1;const len=a.contours.length;for(let i=0;i<len;i++){const aVertex=a.contours[i];for(let j=0;j<len;j++){const bVertex=b.contours[j];if(!equals$7(aVertex,bVertex))return!1}}return!0},fromGeom2:geometry=>{const contours=toOutlines(geometry).map((outline=>outline.map((point=>fromVec2([0,0,0],point)))));return create$2(contours)},fromVertices:vertices=>{if(!Array.isArray(vertices))throw new Error("the given vertices must be an array");if(vertices.length<3)throw new Error("the given vertices must contain THREE or more vertices");const cloned=vertices.map((vertex=>3===vertex.length?vertex:fromVec2([0,0,0],vertex)));return create$2([cloned])},isA:isA,reverse:slice=>{const contours=slice.contours.map((contour=>contour.slice().reverse()));return create$2(contours)},toEdges:slice=>{const edges=[];return slice.contours.forEach((contour=>{contour.forEach(((vertex,i)=>{const next=contour[(i+1)%contour.length];edges.push([vertex,next])}))})),edges},toVertices:slice=>{const vertices=[];return slice.contours.forEach((contour=>{contour.forEach((vertex=>{vertices.push(vertex)}))})),vertices},toPolygons:slice=>{const hierarchy=new PolygonHierarchy(slice),polygons=[];return hierarchy.roots.forEach((({solid:solid,holes:holes})=>{let index=solid.length;const holesIndex=[];holes.forEach(((hole,i)=>{holesIndex.push(index),index+=hole.length}));const vertices=[solid,...holes].flat(),getVertex=i=>hierarchy.to3D(vertices[i]),indices=((data,holeIndices,dim=2)=>{const hasHoles=holeIndices&&holeIndices.length,outerLen=hasHoles?holeIndices[0]*dim:data.length;let outerNode=linkedPolygon(data,0,outerLen,dim,!0);const triangles=[];if(!outerNode||outerNode.next===outerNode.prev)return triangles;let minX,minY,maxX,maxY,invSize;if(hasHoles&&(outerNode=((data,holeIndices,outerNode,dim)=>{const queue=[];for(let i=0,len=holeIndices.length;i<len;i++){const start=holeIndices[i]*dim,end=i<len-1?holeIndices[i+1]*dim:data.length,list=linkedPolygon(data,start,end,dim,!1);list===list.next&&(list.steiner=!0),queue.push(getLeftmost(list))}queue.sort(((a,b)=>a.x-b.x));for(let i=0;i<queue.length;i++)outerNode=eliminateHole(queue[i],outerNode),outerNode=filterPoints(outerNode,outerNode.next);return outerNode})(data,holeIndices,outerNode,dim)),data.length>80*dim){minX=maxX=data[0],minY=maxY=data[1];for(let i=dim;i<outerLen;i+=dim){const x=data[i],y=data[i+1];x<minX&&(minX=x),y<minY&&(minY=y),x>maxX&&(maxX=x),y>maxY&&(maxY=y)}invSize=Math.max(maxX-minX,maxY-minY),invSize=0!==invSize?1/invSize:0}return earcutLinked(outerNode,triangles,dim,minX,minY,invSize),triangles})(vertices.flat(),holesIndex);for(let i=0;i<indices.length;i+=3){const tri=indices.slice(i,i+3).map(getVertex);polygons.push(fromVerticesAndPlane(tri,hierarchy.plane))}})),polygons},toString:slice=>{let result="slice ("+slice.contours.length+" contours):\n[\n";return slice.contours.forEach((contour=>{result+=" ["+contour.map(toString$b).join()+"],\n"})),result+="]\n",result},transform:(matrix,slice)=>{const contours=slice.contours.map((contour=>contour.map((vertex=>transform$c([0,0,0],vertex,matrix)))));return create$2(contours)},validate:object=>{if(!isA(object))throw new Error("invalid slice structure");const slicePlane=calculatePlane(object);object.contours.forEach(((contour,i)=>{if(contour.length<3)throw new Error(`slice contour ${i} must contain at least 3 vertices`);const contourPlane=plane(create$7(contour));if(!equals$5(slicePlane,contourPlane))throw new Error("slice contours must be coplanar");for(let i=0;i<contour.length;i++){if(!contour[i].every(Number.isFinite))throw new Error(`slice contour ${i} must contain finite vertices`);const j=(i+1)%contour.length;if(equals$7(contour[i],contour[j]))throw new Error(`slice contour ${i} has duplicate vertex ${contour[i]}`)}}))}});const direction$1=line=>{const vector=normal([0,0],line);return negate(vector,vector),vector},origin$1=line=>scale$1([0,0],line,line[2]),copy$1=(out,line)=>(out[0]=line[0],out[1]=line[1],out[2]=line[2],out),fromPoints$1=(out,point1,point2)=>{const vector=subtract$1([0,0],point2,point1);normal(vector,vector),normalize(vector,vector);const distance=dot$1(point1,vector);return out[0]=vector[0],out[1]=vector[1],out[2]=distance,out},fromValues=(x,y,d)=>{const out=[0,1,0];return out[0]=x,out[1]=y,out[2]=d,out},solve2Linear=(a,b,c,d,u,v)=>{const invdet=1/(a*d-b*c);let x=u*d-b*v,y=-u*c+a*v;return x*=invdet,y*=invdet,[x,y]};Object.freeze({__proto__:null,clone:line=>{const out=[0,1,0];return out[0]=line[0],out[1]=line[1],out[2]=line[2],out},closestPoint:(line,point)=>{const orig=origin$1(line),dir=direction$1(line),v=subtract$1([0,0],point,orig),dist=dot$1(v,dir);return scale$1(v,dir,dist),add(v,v,orig),v},copy:copy$1,create:()=>[0,1,0],direction:direction$1,distanceToPoint:(line,point)=>{let distance=dot$1(point,line);return distance=Math.abs(distance-line[2]),distance},equals:(line1,line2)=>line1[0]===line2[0]&&line1[1]===line2[1]&&line1[2]===line2[2],fromPoints:fromPoints$1,fromValues:fromValues,intersectPointOfLines:(line1,line2)=>{const point=solve2Linear(line1[0],line1[1],line2[0],line2[1],line1[2],line2[2]);return clone$8(point)},origin:origin$1,reverse:(out,line)=>{const normal=negate([0,0],line),distance=-line[2];return copy$1(out,fromValues(normal[0],normal[1],distance))},toString:line=>`line2: (${line[0].toFixed(7)}, ${line[1].toFixed(7)}, ${line[2].toFixed(7)})`,transform:(out,line,matrix)=>{const org=origin$1(line),dir=direction$1(line);return transform$b(org,org,matrix),transform$b(dir,dir,matrix),fromPoints$1(out,org,dir)},xAtY:(line,y)=>{let x=(line[2]-line[1]*y)/line[0];return Number.isNaN(x)&&(x=origin$1(line)[0]),x}});const create=()=>[fromValues$3(0,0,0),fromValues$3(0,0,1)],closestPoint=(line,point)=>{const lPoint=line[0],lDirection=line[1],a=dot$2(subtract$3([0,0,0],point,lPoint),lDirection),b=dot$2(lDirection,lDirection),closestPoint=scale$3([0,0,0],lDirection,a/b);return add$1(closestPoint,closestPoint,lPoint),closestPoint},fromPointAndDirection=(out,point,direction)=>{const unit=normalize$1([0,0,0],direction);return copy$4(out[0],point),copy$4(out[1],unit),out};Object.freeze({__proto__:null,clone:line=>{const out=create();return copy$4(out[0],line[0]),copy$4(out[1],line[1]),out},closestPoint:closestPoint,copy:(out,line)=>(copy$4(out[0],line[0]),copy$4(out[1],line[1]),out),create:create,direction:line=>line[1],distanceToPoint:(line,point)=>{const closest=closestPoint(line,point),distanceVector=subtract$3([0,0,0],point,closest);return length$2(distanceVector)},equals:(line1,line2)=>!!equals$7(line1[1],line2[1])&&!!equals$7(line1[0],line2[0]),fromPlanes:(out,plane1,plane2)=>{let direction=cross$1([0,0,0],plane1,plane2),length=length$2(direction);if(length<EPS)throw new Error("parallel planes do not intersect");length=1/length,direction=scale$3(direction,direction,length);const absX=Math.abs(direction[0]),absY=Math.abs(direction[1]),absZ=Math.abs(direction[2]);let origin,r;return absX>=absY&&absX>=absZ?(r=solve2Linear(plane1[1],plane1[2],plane2[1],plane2[2],plane1[3],plane2[3]),origin=fromValues$3(0,r[0],r[1])):absY>=absX&&absY>=absZ?(r=solve2Linear(plane1[0],plane1[2],plane2[0],plane2[2],plane1[3],plane2[3]),origin=fromValues$3(r[0],0,r[1])):(r=solve2Linear(plane1[0],plane1[1],plane2[0],plane2[1],plane1[3],plane2[3]),origin=fromValues$3(r[0],r[1],0)),fromPointAndDirection(out,origin,direction)},fromPointAndDirection:fromPointAndDirection,fromPoints:(out,point1,point2)=>{const direction=subtract$3([0,0,0],point2,point1);return fromPointAndDirection(out,point1,direction)},intersectPointOfLineAndPlane:(line,plane)=>{const pNormal=plane,pw=plane[3],lPoint=line[0],lDirection=line[1],labda=(pw-dot$2(pNormal,lPoint))/dot$2(pNormal,lDirection);return add$1([0,0,0],lPoint,scale$3([0,0,0],lDirection,labda))},origin:line=>line[0],reverse:(out,line)=>{const point=clone$9(line[0]),direction=negate$1([0,0,0],line[1]);return fromPointAndDirection(out,point,direction)},toString:line=>{const point=line[0],direction=line[1];return`line3: point: (${point[0].toFixed(7)}, ${point[1].toFixed(7)}, ${point[2].toFixed(7)}) direction: (${direction[0].toFixed(7)}, ${direction[1].toFixed(7)}, ${direction[2].toFixed(7)})`},transform:(out,line,matrix)=>{const point=line[0],direction=line[1],pointPlusDirection=add$1([0,0,0],point,direction),newPoint=transform$c([0,0,0],point,matrix),newPointPlusDirection=transform$c(pointPlusDirection,pointPlusDirection,matrix),newDirection=subtract$3(newPointPlusDirection,newPointPlusDirection,newPoint);return fromPointAndDirection(out,newPoint,newDirection)}});const isNumberArray=(array,dimension)=>!!(Array.isArray(array)&&array.length>=dimension)&&array.every((n=>Number.isFinite(n))),deserialize=(options,input)=>{const defaults={filename:"obj",output:"script",orientation:"outward",version:"3.0.0-alpha.0",addMetaData:!0};options=Object.assign({},defaults,options);const{output:output}=options;options&&options.statusCallback&&options.statusCallback({progress:0});const{positions:positions,groups:groups}=getGroups(input),result="script"===output?stringify(positions,groups,options):objectify(positions,groups,options);return options&&options.statusCallback&&options.statusCallback({progress:100}),result},getGroups=(data,options)=>{let groups=[];const positions=[];let material=null;groups.push({faces:[],colors:[],name:"default",line:0});const handleG=(command,values)=>{const group={faces:[],colors:[],name:""};values&&values.length>0&&(group.name=values.join(" ")),groups.push(group)},handleV=(command,values)=>{const x=parseFloat(values[0]),y=parseFloat(values[1]),z=parseFloat(values[2]);positions.push([x,y,z])},handleF=(command,values)=>{const facerefs=values.map((value=>{const refs=value.match(/[0-9+\-eE]+/g);let ref=parseInt(refs[0]);return ref<0?ref=positions.length+ref:ref--,ref})),group=groups.pop();group.faces.push(facerefs),group.colors.push(material),groups.push(group)},handleMtl=(command,values)=>{if(material=null,values&&values.length>0){const c=(s=values[0],cssColors[s.toLowerCase()]);c&&(material=[c[0],c[1],c[2],1])}var s},lines=data.split(/\n/);for(let i=0;i<lines.length;i++){const line=lines[i].trim();if(line&&line.length>0){let values=line.match(/\S+/g);if(values){const command=values[0];switch(values=values.slice(1),command){case"g":handleG(0,values);break;case"v":handleV(0,values);break;case"f":handleF(0,values);break;case"usemtl":handleMtl(0,values)}}}}return groups=groups.filter((group=>group.faces.length>0)),{positions:positions,groups:groups}},objectify=(points,groups,options)=>{const geometries=groups.map((group=>(options=>{const{points:points,faces:faces,colors:colors,orientation:orientation}=Object.assign({},{points:[],faces:[],colors:void 0,orientation:"outward"},options);if(!Array.isArray(points)||!Array.isArray(faces))throw new Error("points and faces must be arrays");if(points.length<3)throw new Error("three or more points are required");if(faces.length<1)throw new Error("one or more faces are required");if(colors){if(!Array.isArray(colors))throw new Error("colors must be an array");if(colors.length!==faces.length)throw new Error("faces and colors must have the same length")}points.forEach(((vertex,i)=>{if(!isNumberArray(vertex,3))throw new Error(`vertex ${i} must be an array of X, Y, Z values`)})),faces.forEach(((face,i)=>{if(face.length<3)throw new Error(`face ${i} must contain 3 or more indexes`);if(!isNumberArray(face,face.length))throw new Error(`face ${i} must be an array of numbers`)})),"outward"!==orientation&&faces.forEach((face=>face.reverse()));const polygons=faces.map(((face,findex)=>{const polygon=create$7(face.map((pindex=>points[pindex])));return colors&&colors[findex]&&(polygon.color=colors[findex]),polygon}));return create$8(polygons)})({orientation:options.orientation,points:points,faces:group.faces,colors:group.colors})));return geometries},stringify=(positions,groups,options)=>{const{filename:filename,addMetaData:addMetaData,version:version}=options;let code=addMetaData?`//\n// Produced by JSCAD IO Library : OBJ Deserializer (${version})\n// date: ${new Date}\n// source: ${filename}\n//\n `:"";return code+=`import * from '@jscad/modeling'\n\n// groups: ${groups.length}\n// points: ${positions.length}\nexport const main = () => {\n // points are common to all geometries\n${(points=>{let code=" let points = [\n";return points.forEach((point=>code+=` [${point}],\n`)),code+=" ]",code})(positions)}\n\n let geometries = [\n${(groups=>{let code="";return groups.forEach(((group,index)=>code+=` group${index}(points), // ${group.name}\n`)),code})(groups)} ]\n return geometries\n}\n\n${((groups,options)=>{let code="";return groups.forEach(((group,index)=>{const faces=group.faces,colors=group.colors;code+=`\n// group : ${group.name}\n// faces: ${faces.length}\n`,code+=`const group${index} = (points) => {\n${(faces=>{let code=" let faces = [\n";return faces.forEach((face=>code+=` [${face}],\n`)),code+=" ]",code})(faces)}\n${(colors=>{let code=" let colors = [\n";return colors.forEach((c=>{code+=c?` [${c}],\n`:" null,\n"})),code+=" ]",code})(colors)}\n return polyhedron({ orientation: '${options.orientation}', points, faces, colors })\n}\n`})),code})(groups,options)}\n`,code},mimeType="model/obj";export{deserialize,mimeType};
@@ -0,0 +1,14 @@
1
+ /**
2
+ * OBJ Deserializer for JSCAD
3
+ * @module @jscad/obj-deserializer
4
+ * @version 3.0.0-alpha.0
5
+ * @license MIT
6
+ */
7
+ var global,factory;global=this,factory=function(exports){
8
+ /**
9
+ * Constructive Solid Geometry (CSG) Library for JSCAD
10
+ * @module @jscad/modeling
11
+ * @version 3.0.0-alpha.0
12
+ * @license MIT
13
+ */
14
+ const cssColors={black:[0,0,0],silver:[192/255,192/255,192/255],gray:[128/255,128/255,128/255],white:[1,1,1],maroon:[128/255,0,0],red:[1,0,0],purple:[128/255,0,128/255],fuchsia:[1,0,1],green:[0,128/255,0],lime:[0,1,0],olive:[128/255,128/255,0],yellow:[1,1,0],navy:[0,0,128/255],blue:[0,0,1],teal:[0,128/255,128/255],aqua:[0,1,1],aliceblue:[240/255,248/255,1],antiquewhite:[250/255,235/255,215/255],aquamarine:[127/255,1,212/255],azure:[240/255,1,1],beige:[245/255,245/255,220/255],bisque:[1,228/255,196/255],blanchedalmond:[1,235/255,205/255],blueviolet:[138/255,43/255,226/255],brown:[165/255,42/255,42/255],burlywood:[222/255,184/255,135/255],cadetblue:[95/255,158/255,160/255],chartreuse:[127/255,1,0],chocolate:[210/255,105/255,30/255],coral:[1,127/255,80/255],cornflowerblue:[100/255,149/255,237/255],cornsilk:[1,248/255,220/255],crimson:[220/255,20/255,60/255],cyan:[0,1,1],darkblue:[0,0,139/255],darkcyan:[0,139/255,139/255],darkgoldenrod:[184/255,134/255,11/255],darkgray:[169/255,169/255,169/255],darkgreen:[0,100/255,0],darkgrey:[169/255,169/255,169/255],darkkhaki:[189/255,183/255,107/255],darkmagenta:[139/255,0,139/255],darkolivegreen:[85/255,107/255,47/255],darkorange:[1,140/255,0],darkorchid:[.6,50/255,.8],darkred:[139/255,0,0],darksalmon:[233/255,150/255,122/255],darkseagreen:[143/255,188/255,143/255],darkslateblue:[72/255,61/255,139/255],darkslategray:[47/255,79/255,79/255],darkslategrey:[47/255,79/255,79/255],darkturquoise:[0,206/255,209/255],darkviolet:[148/255,0,211/255],deeppink:[1,20/255,147/255],deepskyblue:[0,191/255,1],dimgray:[105/255,105/255,105/255],dimgrey:[105/255,105/255,105/255],dodgerblue:[30/255,144/255,1],firebrick:[178/255,34/255,34/255],floralwhite:[1,250/255,240/255],forestgreen:[34/255,139/255,34/255],gainsboro:[220/255,220/255,220/255],ghostwhite:[248/255,248/255,1],gold:[1,215/255,0],goldenrod:[218/255,165/255,32/255],greenyellow:[173/255,1,47/255],grey:[128/255,128/255,128/255],honeydew:[240/255,1,240/255],hotpink:[1,105/255,180/255],indianred:[205/255,92/255,92/255],indigo:[75/255,0,130/255],ivory:[1,1,240/255],khaki:[240/255,230/255,140/255],lavender:[230/255,230/255,250/255],lavenderblush:[1,240/255,245/255],lawngreen:[124/255,252/255,0],lemonchiffon:[1,250/255,205/255],lightblue:[173/255,216/255,230/255],lightcoral:[240/255,128/255,128/255],lightcyan:[224/255,1,1],lightgoldenrodyellow:[250/255,250/255,210/255],lightgray:[211/255,211/255,211/255],lightgreen:[144/255,238/255,144/255],lightgrey:[211/255,211/255,211/255],lightpink:[1,182/255,193/255],lightsalmon:[1,160/255,122/255],lightseagreen:[32/255,178/255,170/255],lightskyblue:[135/255,206/255,250/255],lightslategray:[119/255,136/255,.6],lightslategrey:[119/255,136/255,.6],lightsteelblue:[176/255,196/255,222/255],lightyellow:[1,1,224/255],limegreen:[50/255,205/255,50/255],linen:[250/255,240/255,230/255],magenta:[1,0,1],mediumaquamarine:[.4,205/255,170/255],mediumblue:[0,0,205/255],mediumorchid:[186/255,85/255,211/255],mediumpurple:[147/255,112/255,219/255],mediumseagreen:[60/255,179/255,113/255],mediumslateblue:[123/255,104/255,238/255],mediumspringgreen:[0,250/255,154/255],mediumturquoise:[72/255,209/255,.8],mediumvioletred:[199/255,21/255,133/255],midnightblue:[25/255,25/255,112/255],mintcream:[245/255,1,250/255],mistyrose:[1,228/255,225/255],moccasin:[1,228/255,181/255],navajowhite:[1,222/255,173/255],oldlace:[253/255,245/255,230/255],olivedrab:[107/255,142/255,35/255],orange:[1,165/255,0],orangered:[1,69/255,0],orchid:[218/255,112/255,214/255],palegoldenrod:[238/255,232/255,170/255],palegreen:[152/255,251/255,152/255],paleturquoise:[175/255,238/255,238/255],palevioletred:[219/255,112/255,147/255],papayawhip:[1,239/255,213/255],peachpuff:[1,218/255,185/255],peru:[205/255,133/255,63/255],pink:[1,192/255,203/255],plum:[221/255,160/255,221/255],powderblue:[176/255,224/255,230/255],rosybrown:[188/255,143/255,143/255],royalblue:[65/255,105/255,225/255],saddlebrown:[139/255,69/255,19/255],salmon:[250/255,128/255,114/255],sandybrown:[244/255,164/255,96/255],seagreen:[46/255,139/255,87/255],seashell:[1,245/255,238/255],sienna:[160/255,82/255,45/255],skyblue:[135/255,206/255,235/255],slateblue:[106/255,90/255,205/255],slategray:[112/255,128/255,144/255],slategrey:[112/255,128/255,144/255],snow:[1,250/255,250/255],springgreen:[0,1,127/255],steelblue:[70/255,130/255,180/255],tan:[210/255,180/255,140/255],thistle:[216/255,191/255,216/255],tomato:[1,99/255,71/255],turquoise:[64/255,224/255,208/255],violet:[238/255,130/255,238/255],wheat:[245/255,222/255,179/255],whitesmoke:[245/255,245/255,245/255],yellowgreen:[154/255,205/255,50/255]},clone$a=matrix=>{const out=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];return out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out},copy$5=(out,matrix)=>(out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out),EPS=1e-5,TAU=2*Math.PI,rezero=n=>Math.abs(n)<1e-13?0:n,sin=radians=>rezero(Math.sin(radians)),cos=radians=>rezero(Math.cos(radians)),identity=out=>(out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out),fromRotation=(out,rad,axis)=>{let[x,y,z]=axis;const lengthSquared=x*x+y*y+z*z;if(Math.abs(lengthSquared)<EPS)return identity(out);const len=1/Math.sqrt(lengthSquared);x*=len,y*=len,z*=len;const s=sin(rad),c=cos(rad),t=1-c;return out[0]=x*x*t+c,out[1]=y*x*t+z*s,out[2]=z*x*t-y*s,out[3]=0,out[4]=x*y*t-z*s,out[5]=y*y*t+c,out[6]=z*y*t+x*s,out[7]=0,out[8]=x*z*t+y*s,out[9]=y*z*t-x*s,out[10]=z*z*t+c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},abs$1=(out,vector)=>(out[0]=Math.abs(vector[0]),out[1]=Math.abs(vector[1]),out[2]=Math.abs(vector[2]),out),add$1=(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out[2]=a[2]+b[2],out),dot$2=(a,b)=>a[0]*b[0]+a[1]*b[1]+a[2]*b[2],clone$9=vector=>{const out=[0,0,0];return out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out},copy$4=(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out),cross$1=(out,a,b)=>{const ax=a[0],ay=a[1],az=a[2],bx=b[0],by=b[1],bz=b[2];return out[0]=ay*bz-az*by,out[1]=az*bx-ax*bz,out[2]=ax*by-ay*bx,out},equals$7=(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2],fromScalar$2=(out,scalar)=>(out[0]=scalar,out[1]=scalar,out[2]=scalar,out),fromValues$3=(x,y,z)=>{const out=[0,0,0];return out[0]=x,out[1]=y,out[2]=z,out},fromVec2=(out,vector,z=0)=>(out[0]=vector[0],out[1]=vector[1],out[2]=z,out),length$2=vector=>{const x=vector[0],y=vector[1],z=vector[2];return Math.sqrt(x*x+y*y+z*z)},max$2=(out,a,b)=>(out[0]=Math.max(a[0],b[0]),out[1]=Math.max(a[1],b[1]),out[2]=Math.max(a[2],b[2]),out),min$2=(out,a,b)=>(out[0]=Math.min(a[0],b[0]),out[1]=Math.min(a[1],b[1]),out[2]=Math.min(a[2],b[2]),out),multiply$2=(out,a,b)=>(out[0]=a[0]*b[0],out[1]=a[1]*b[1],out[2]=a[2]*b[2],out),negate$1=(out,vector)=>(out[0]=-vector[0],out[1]=-vector[1],out[2]=-vector[2],out),normalize$1=(out,vector)=>{const x=vector[0],y=vector[1],z=vector[2];let len=x*x+y*y+z*z;return len>0&&(len=1/Math.sqrt(len)),out[0]=x*len,out[1]=y*len,out[2]=z*len,out},orthogonal=(out,vector)=>{const bV=abs$1([0,0,0],vector),b0=0+(bV[0]<bV[1]&&bV[0]<bV[2]),b1=0+(bV[1]<=bV[0]&&bV[1]<bV[2]),b2=0+(bV[2]<=bV[0]&&bV[2]<=bV[1]);return cross$1(out,vector,[b0,b1,b2])},scale$3=(out,vector,amount)=>(out[0]=vector[0]*amount,out[1]=vector[1]*amount,out[2]=vector[2]*amount,out),squaredDistance$1=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1],z=b[2]-a[2];return x*x+y*y+z*z},subtract$3=(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out[2]=a[2]-b[2],out),toString$b=vec=>`[${vec[0].toFixed(7)}, ${vec[1].toFixed(7)}, ${vec[2].toFixed(7)}]`,transform$c=(out,vector,matrix)=>{const x=vector[0],y=vector[1],z=vector[2];let w=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15];return w=w||1,out[0]=(matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12])/w,out[1]=(matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13])/w,out[2]=(matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14])/w,out};Object.freeze({__proto__:null,abs:abs$1,add:add$1,angle:(a,b)=>{const ax=a[0],ay=a[1],az=a[2],bx=b[0],by=b[1],bz=b[2],mag=Math.sqrt(ax*ax+ay*ay+az*az)*Math.sqrt(bx*bx+by*by+bz*bz),cosine=mag&&dot$2(a,b)/mag;return Math.acos(Math.min(Math.max(cosine,-1),1))},clone:clone$9,copy:copy$4,create:()=>[0,0,0],cross:cross$1,distance:(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1],z=b[2]-a[2];return Math.sqrt(x*x+y*y+z*z)},divide:(out,a,b)=>(out[0]=a[0]/b[0],out[1]=a[1]/b[1],out[2]=a[2]/b[2],out),dot:dot$2,equals:equals$7,fromScalar:fromScalar$2,fromValues:fromValues$3,fromVec2:fromVec2,length:length$2,lerp:(out,a,b,t)=>(out[0]=a[0]+t*(b[0]-a[0]),out[1]=a[1]+t*(b[1]-a[1]),out[2]=a[2]+t*(b[2]-a[2]),out),max:max$2,min:min$2,multiply:multiply$2,negate:negate$1,normalize:normalize$1,orthogonal:orthogonal,rotateX:(out,vector,origin,radians)=>{const p=[],r=[];return p[0]=vector[0]-origin[0],p[1]=vector[1]-origin[1],p[2]=vector[2]-origin[2],r[0]=p[0],r[1]=p[1]*Math.cos(radians)-p[2]*Math.sin(radians),r[2]=p[1]*Math.sin(radians)+p[2]*Math.cos(radians),out[0]=r[0]+origin[0],out[1]=r[1]+origin[1],out[2]=r[2]+origin[2],out},rotateY:(out,vector,origin,radians)=>{const p=[],r=[];return p[0]=vector[0]-origin[0],p[1]=vector[1]-origin[1],p[2]=vector[2]-origin[2],r[0]=p[2]*Math.sin(radians)+p[0]*Math.cos(radians),r[1]=p[1],r[2]=p[2]*Math.cos(radians)-p[0]*Math.sin(radians),out[0]=r[0]+origin[0],out[1]=r[1]+origin[1],out[2]=r[2]+origin[2],out},rotateZ:(out,vector,origin,radians)=>{const p=[],r=[];return p[0]=vector[0]-origin[0],p[1]=vector[1]-origin[1],r[0]=p[0]*Math.cos(radians)-p[1]*Math.sin(radians),r[1]=p[0]*Math.sin(radians)+p[1]*Math.cos(radians),out[0]=r[0]+origin[0],out[1]=r[1]+origin[1],out[2]=vector[2],out},scale:scale$3,snap:(out,vector,epsilon)=>(out[0]=Math.round(vector[0]/epsilon)*epsilon+0,out[1]=Math.round(vector[1]/epsilon)*epsilon+0,out[2]=Math.round(vector[2]/epsilon)*epsilon+0,out),squaredDistance:squaredDistance$1,squaredLength:vector=>{const x=vector[0],y=vector[1],z=vector[2];return x*x+y*y+z*z},subtract:subtract$3,toString:toString$b,transform:transform$c});const isIdentity=matrix=>1===matrix[0]&&0===matrix[1]&&0===matrix[2]&&0===matrix[3]&&0===matrix[4]&&1===matrix[5]&&0===matrix[6]&&0===matrix[7]&&0===matrix[8]&&0===matrix[9]&&1===matrix[10]&&0===matrix[11]&&0===matrix[12]&&0===matrix[13]&&0===matrix[14]&&1===matrix[15],isMirroring=matrix=>{const x=matrix[4]*matrix[9]-matrix[8]*matrix[5],y=matrix[8]*matrix[1]-matrix[0]*matrix[9],z=matrix[0]*matrix[5]-matrix[4]*matrix[1];return x*matrix[2]+y*matrix[6]+z*matrix[10]<0},isZero=num=>Math.abs(num)<Number.EPSILON,multiply$1=(out,a,b)=>{const a00=a[0],a01=a[1],a02=a[2],a03=a[3],a10=a[4],a11=a[5],a12=a[6],a13=a[7],a20=a[8],a21=a[9],a22=a[10],a23=a[11],a30=a[12],a31=a[13],a32=a[14],a33=a[15];let b0=b[0],b1=b[1],b2=b[2],b3=b[3];return out[0]=b0*a00+b1*a10+b2*a20+b3*a30,out[1]=b0*a01+b1*a11+b2*a21+b3*a31,out[2]=b0*a02+b1*a12+b2*a22+b3*a32,out[3]=b0*a03+b1*a13+b2*a23+b3*a33,b0=b[4],b1=b[5],b2=b[6],b3=b[7],out[4]=b0*a00+b1*a10+b2*a20+b3*a30,out[5]=b0*a01+b1*a11+b2*a21+b3*a31,out[6]=b0*a02+b1*a12+b2*a22+b3*a32,out[7]=b0*a03+b1*a13+b2*a23+b3*a33,b0=b[8],b1=b[9],b2=b[10],b3=b[11],out[8]=b0*a00+b1*a10+b2*a20+b3*a30,out[9]=b0*a01+b1*a11+b2*a21+b3*a31,out[10]=b0*a02+b1*a12+b2*a22+b3*a32,out[11]=b0*a03+b1*a13+b2*a23+b3*a33,b0=b[12],b1=b[13],b2=b[14],b3=b[15],out[12]=b0*a00+b1*a10+b2*a20+b3*a30,out[13]=b0*a01+b1*a11+b2*a21+b3*a31,out[14]=b0*a02+b1*a12+b2*a22+b3*a32,out[15]=b0*a03+b1*a13+b2*a23+b3*a33,out};Object.freeze({__proto__:null,add:(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out[2]=a[2]+b[2],out[3]=a[3]+b[3],out[4]=a[4]+b[4],out[5]=a[5]+b[5],out[6]=a[6]+b[6],out[7]=a[7]+b[7],out[8]=a[8]+b[8],out[9]=a[9]+b[9],out[10]=a[10]+b[10],out[11]=a[11]+b[11],out[12]=a[12]+b[12],out[13]=a[13]+b[13],out[14]=a[14]+b[14],out[15]=a[15]+b[15],out),clone:clone$a,copy:copy$5,create:()=>[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],equals:(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3]&&a[4]===b[4]&&a[5]===b[5]&&a[6]===b[6]&&a[7]===b[7]&&a[8]===b[8]&&a[9]===b[9]&&a[10]===b[10]&&a[11]===b[11]&&a[12]===b[12]&&a[13]===b[13]&&a[14]===b[14]&&a[15]===b[15],fromRotation:fromRotation,fromScaling:(out,vector)=>(out[0]=vector[0],out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=vector[1],out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=vector[2],out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out),fromTaitBryanRotation:(out,yaw,pitch,roll)=>{const sy=sin(yaw),cy=cos(yaw),sp=sin(pitch),cp=cos(pitch),sr=sin(roll),cr=cos(roll);return out[0]=cp*cy,out[1]=cp*sy,out[2]=-sp,out[3]=0,out[4]=sr*sp*cy-cr*sy,out[5]=cr*cy+sr*sp*sy,out[6]=sr*cp,out[7]=0,out[8]=sr*sy+cr*sp*cy,out[9]=cr*sp*sy-sr*cy,out[10]=cr*cp,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromTranslation:(out,vector)=>(out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=vector[0],out[13]=vector[1],out[14]=vector[2],out[15]=1,out),fromValues:(m00,m01,m02,m03,m10,m11,m12,m13,m20,m21,m22,m23,m30,m31,m32,m33)=>{const out=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];return out[0]=m00,out[1]=m01,out[2]=m02,out[3]=m03,out[4]=m10,out[5]=m11,out[6]=m12,out[7]=m13,out[8]=m20,out[9]=m21,out[10]=m22,out[11]=m23,out[12]=m30,out[13]=m31,out[14]=m32,out[15]=m33,out},fromVectorRotation:(out,source,target)=>{const sourceNormal=normalize$1([0,0,0],source),targetNormal=normalize$1([0,0,0],target),axis=cross$1([0,0,0],targetNormal,sourceNormal),cosA=dot$2(targetNormal,sourceNormal);if(-1===cosA)return fromRotation(out,Math.PI,orthogonal(axis,sourceNormal));const k=1/(1+cosA);return out[0]=axis[0]*axis[0]*k+cosA,out[1]=axis[1]*axis[0]*k-axis[2],out[2]=axis[2]*axis[0]*k+axis[1],out[3]=0,out[4]=axis[0]*axis[1]*k+axis[2],out[5]=axis[1]*axis[1]*k+cosA,out[6]=axis[2]*axis[1]*k-axis[0],out[7]=0,out[8]=axis[0]*axis[2]*k-axis[1],out[9]=axis[1]*axis[2]*k+axis[0],out[10]=axis[2]*axis[2]*k+cosA,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromXRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=c,out[6]=s,out[7]=0,out[8]=0,out[9]=-s,out[10]=c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromYRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=c,out[1]=0,out[2]=-s,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=s,out[9]=0,out[10]=c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromZRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=c,out[1]=s,out[2]=0,out[3]=0,out[4]=-s,out[5]=c,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},identity:identity,invert:(out,matrix)=>{const a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],a30=matrix[12],a31=matrix[13],a32=matrix[14],a33=matrix[15],b00=a00*a11-a01*a10,b01=a00*a12-a02*a10,b02=a00*a13-a03*a10,b03=a01*a12-a02*a11,b04=a01*a13-a03*a11,b05=a02*a13-a03*a12,b06=a20*a31-a21*a30,b07=a20*a32-a22*a30,b08=a20*a33-a23*a30,b09=a21*a32-a22*a31,b10=a21*a33-a23*a31,b11=a22*a33-a23*a32;let det=b00*b11-b01*b10+b02*b09+b03*b08-b04*b07+b05*b06;return det?(det=1/det,out[0]=(a11*b11-a12*b10+a13*b09)*det,out[1]=(a02*b10-a01*b11-a03*b09)*det,out[2]=(a31*b05-a32*b04+a33*b03)*det,out[3]=(a22*b04-a21*b05-a23*b03)*det,out[4]=(a12*b08-a10*b11-a13*b07)*det,out[5]=(a00*b11-a02*b08+a03*b07)*det,out[6]=(a32*b02-a30*b05-a33*b01)*det,out[7]=(a20*b05-a22*b02+a23*b01)*det,out[8]=(a10*b10-a11*b08+a13*b06)*det,out[9]=(a01*b08-a00*b10-a03*b06)*det,out[10]=(a30*b04-a31*b02+a33*b00)*det,out[11]=(a21*b02-a20*b04-a23*b00)*det,out[12]=(a11*b07-a10*b09-a12*b06)*det,out[13]=(a00*b09-a01*b07+a02*b06)*det,out[14]=(a31*b01-a30*b03-a32*b00)*det,out[15]=(a20*b03-a21*b01+a22*b00)*det,out):null},isIdentity:isIdentity,isMirroring:isMirroring,isOnlyTransformScale:matrix=>isZero(matrix[1])&&isZero(matrix[2])&&isZero(matrix[3])&&isZero(matrix[4])&&isZero(matrix[6])&&isZero(matrix[7])&&isZero(matrix[8])&&isZero(matrix[9])&&isZero(matrix[11])&&1===matrix[15],mirrorByPlane:(out,plane)=>{const[nx,ny,nz,w]=plane;return out[0]=1-2*nx*nx,out[1]=-2*ny*nx,out[2]=-2*nz*nx,out[3]=0,out[4]=-2*nx*ny,out[5]=1-2*ny*ny,out[6]=-2*nz*ny,out[7]=0,out[8]=-2*nx*nz,out[9]=-2*ny*nz,out[10]=1-2*nz*nz,out[11]=0,out[12]=2*nx*w,out[13]=2*ny*w,out[14]=2*nz*w,out[15]=1,out},multiply:multiply$1,rotate:(out,matrix,radians,axis)=>{let[x,y,z]=axis;const lengthSquared=x*x+y*y+z*z;if(Math.abs(lengthSquared)<EPS)return copy$5(out,matrix);const len=1/Math.sqrt(lengthSquared);x*=len,y*=len,z*=len;const s=sin(radians),c=cos(radians),t=1-c,a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],b00=x*x*t+c,b01=y*x*t+z*s,b02=z*x*t-y*s,b10=x*y*t-z*s,b11=y*y*t+c,b12=z*y*t+x*s,b20=x*z*t+y*s,b21=y*z*t-x*s,b22=z*z*t+c;return out[0]=a00*b00+a10*b01+a20*b02,out[1]=a01*b00+a11*b01+a21*b02,out[2]=a02*b00+a12*b01+a22*b02,out[3]=a03*b00+a13*b01+a23*b02,out[4]=a00*b10+a10*b11+a20*b12,out[5]=a01*b10+a11*b11+a21*b12,out[6]=a02*b10+a12*b11+a22*b12,out[7]=a03*b10+a13*b11+a23*b12,out[8]=a00*b20+a10*b21+a20*b22,out[9]=a01*b20+a11*b21+a21*b22,out[10]=a02*b20+a12*b21+a22*b22,out[11]=a03*b20+a13*b21+a23*b22,matrix!==out&&(out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out},rotateX:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11];return matrix!==out&&(out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[4]=a10*c+a20*s,out[5]=a11*c+a21*s,out[6]=a12*c+a22*s,out[7]=a13*c+a23*s,out[8]=a20*c-a10*s,out[9]=a21*c-a11*s,out[10]=a22*c-a12*s,out[11]=a23*c-a13*s,out},rotateY:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11];return matrix!==out&&(out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[0]=a00*c-a20*s,out[1]=a01*c-a21*s,out[2]=a02*c-a22*s,out[3]=a03*c-a23*s,out[8]=a00*s+a20*c,out[9]=a01*s+a21*c,out[10]=a02*s+a22*c,out[11]=a03*s+a23*c,out},rotateZ:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7];return matrix!==out&&(out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[0]=a00*c+a10*s,out[1]=a01*c+a11*s,out[2]=a02*c+a12*s,out[3]=a03*c+a13*s,out[4]=a10*c-a00*s,out[5]=a11*c-a01*s,out[6]=a12*c-a02*s,out[7]=a13*c-a03*s,out},scale:(out,matrix,dimensions)=>{const x=dimensions[0],y=dimensions[1],z=dimensions[2];return out[0]=matrix[0]*x,out[1]=matrix[1]*x,out[2]=matrix[2]*x,out[3]=matrix[3]*x,out[4]=matrix[4]*y,out[5]=matrix[5]*y,out[6]=matrix[6]*y,out[7]=matrix[7]*y,out[8]=matrix[8]*z,out[9]=matrix[9]*z,out[10]=matrix[10]*z,out[11]=matrix[11]*z,out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out},subtract:(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out[2]=a[2]-b[2],out[3]=a[3]-b[3],out[4]=a[4]-b[4],out[5]=a[5]-b[5],out[6]=a[6]-b[6],out[7]=a[7]-b[7],out[8]=a[8]-b[8],out[9]=a[9]-b[9],out[10]=a[10]-b[10],out[11]=a[11]-b[11],out[12]=a[12]-b[12],out[13]=a[13]-b[13],out[14]=a[14]-b[14],out[15]=a[15]-b[15],out),toString:mat=>mat.map((n=>n.toFixed(7))).toString(),translate:(out,matrix,offsets)=>{const x=offsets[0],y=offsets[1],z=offsets[2];let a00,a01,a02,a03,a10,a11,a12,a13,a20,a21,a22,a23;return matrix===out?(out[12]=matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12],out[13]=matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13],out[14]=matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14],out[15]=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15]):(a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],out[0]=a00,out[1]=a01,out[2]=a02,out[3]=a03,out[4]=a10,out[5]=a11,out[6]=a12,out[7]=a13,out[8]=a20,out[9]=a21,out[10]=a22,out[11]=a23,out[12]=a00*x+a10*y+a20*z+matrix[12],out[13]=a01*x+a11*y+a21*z+matrix[13],out[14]=a02*x+a12*y+a22*z+matrix[14],out[15]=a03*x+a13*y+a23*z+matrix[15]),out}});const create$a=(outlines=[])=>({outlines:outlines,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),add=(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out),angleRadians=vector=>Math.atan2(vector[1],vector[0]),angleDegrees=vector=>57.29577951308232*angleRadians(vector),clone$8=vector=>{const out=[0,0];return out[0]=vector[0],out[1]=vector[1],out},cross=(out,a,b)=>(out[0]=0,out[1]=0,out[2]=a[0]*b[1]-a[1]*b[0],out),distance=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1];return Math.sqrt(x*x+y*y)},dot$1=(a,b)=>a[0]*b[0]+a[1]*b[1],equals$6=(a,b)=>a[0]===b[0]&&a[1]===b[1],fromAngleRadians=(out,radians)=>(out[0]=cos(radians),out[1]=sin(radians),out),fromValues$2=(x,y)=>{const out=[0,0];return out[0]=x,out[1]=y,out},max$1=(out,a,b)=>(out[0]=Math.max(a[0],b[0]),out[1]=Math.max(a[1],b[1]),out),min$1=(out,a,b)=>(out[0]=Math.min(a[0],b[0]),out[1]=Math.min(a[1],b[1]),out),negate=(out,vector)=>(out[0]=-vector[0],out[1]=-vector[1],out),rotate$1=(out,vector,origin,radians)=>{const x=vector[0]-origin[0],y=vector[1]-origin[1],c=Math.cos(radians),s=Math.sin(radians);return out[0]=x*c-y*s+origin[0],out[1]=x*s+y*c+origin[1],out},normal=(out,vector)=>rotate$1(out,vector,[0,0],TAU/4),normalize=(out,vector)=>{const x=vector[0],y=vector[1];let len=x*x+y*y;return len>0&&(len=1/Math.sqrt(len)),out[0]=x*len,out[1]=y*len,out},scale$1=(out,vector,amount)=>(out[0]=vector[0]*amount,out[1]=vector[1]*amount,out),subtract$1=(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out),toString$9=vector=>`[${vector[0].toFixed(7)}, ${vector[1].toFixed(7)}]`,transform$b=(out,vector,matrix)=>{const x=vector[0],y=vector[1];return out[0]=matrix[0]*x+matrix[4]*y+matrix[12],out[1]=matrix[1]*x+matrix[5]*y+matrix[13],out};Object.freeze({__proto__:null,abs:(out,vector)=>(out[0]=Math.abs(vector[0]),out[1]=Math.abs(vector[1]),out),add:add,angle:angleRadians,angleDegrees:angleDegrees,angleRadians:angleRadians,clone:clone$8,copy:(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out),create:()=>[0,0],cross:cross,distance:distance,divide:(out,a,b)=>(out[0]=a[0]/b[0],out[1]=a[1]/b[1],out),dot:dot$1,equals:equals$6,fromAngleDegrees:(out,degrees)=>fromAngleRadians(out,.017453292519943295*degrees),fromAngleRadians:fromAngleRadians,fromScalar:(out,scalar)=>(out[0]=scalar,out[1]=scalar,out),fromValues:fromValues$2,length:vector=>Math.sqrt(vector[0]*vector[0]+vector[1]*vector[1]),lerp:(out,a,b,t)=>{const ax=a[0],ay=a[1];return out[0]=ax+t*(b[0]-ax),out[1]=ay+t*(b[1]-ay),out},max:max$1,min:min$1,multiply:(out,a,b)=>(out[0]=a[0]*b[0],out[1]=a[1]*b[1],out),negate:negate,normal:normal,normalize:normalize,rotate:rotate$1,scale:scale$1,snap:(out,vector,epsilon)=>(out[0]=Math.round(vector[0]/epsilon)*epsilon+0,out[1]=Math.round(vector[1]/epsilon)*epsilon+0,out),squaredDistance:(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1];return x*x+y*y},squaredLength:vector=>{const x=vector[0],y=vector[1];return x*x+y*y},subtract:subtract$1,toString:toString$9,transform:transform$b});const popNextSide=(startSide,nextSides)=>{if(1===nextSides.length)return nextSides.pop();const v0=[0,0],startAngle=angleDegrees(subtract$1(v0,startSide[1],startSide[0]));let bestAngle,bestIndex;nextSides.forEach(((nextSide,index)=>{let angle=angleDegrees(subtract$1(v0,nextSide[1],nextSide[0]))-startAngle;angle<-180&&(angle+=360),angle>=180&&(angle-=360),(void 0===bestIndex||angle>bestAngle)&&(bestIndex=index,bestAngle=angle)}));const nextSide=nextSides[bestIndex];return nextSides.splice(bestIndex,1),nextSide},isA$5=object=>!!(object&&"object"==typeof object&&"outlines"in object&&"transforms"in object&&Array.isArray(object.outlines)&&"length"in object.transforms),toOutlines=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.outlines=geometry.outlines.map((outline=>outline.map((point=>transform$b([0,0],point,geometry.transforms))))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).outlines,intersect$1=(p1,p2,p3,p4,endpointTouch=!0)=>{if(p1[0]===p2[0]&&p1[1]===p2[1]||p3[0]===p4[0]&&p3[1]===p4[1])return;const denominator=(p4[1]-p3[1])*(p2[0]-p1[0])-(p4[0]-p3[0])*(p2[1]-p1[1]);if(Math.abs(denominator)<Number.MIN_VALUE)return;const ua=((p4[0]-p3[0])*(p1[1]-p3[1])-(p4[1]-p3[1])*(p1[0]-p3[0]))/denominator,ub=((p2[0]-p1[0])*(p1[1]-p3[1])-(p2[1]-p1[1])*(p1[0]-p3[0]))/denominator;return ua<0||ua>1||ub<0||ub>1||!(endpointTouch||0!==ua&&1!==ua&&0!==ub&&1!==ub)?void 0:[p1[0]+ua*(p2[0]-p1[0]),p1[1]+ua*(p2[1]-p1[1])]};Object.freeze({__proto__:null,clone:geometry=>Object.assign({},geometry),create:create$a,fromSides:sides=>{const pointMap=(sides=>{const pointMap=new Map,edges=(sides=>{const unique=new Map,getUniquePoint=point=>{const key=point.toString();return unique.has(key)?unique.get(key):(unique.set(key,point),point)};return sides.map((side=>side.map(getUniquePoint)))})(sides);return edges.forEach((edge=>{pointMap.has(edge[0])?pointMap.get(edge[0]).push(edge):pointMap.set(edge[0],[edge])})),pointMap})(sides),outlines=[];for(;;){let startSide;for(const[point,edges]of pointMap){if(startSide=edges.shift(),startSide)break;pointMap.delete(point)}if(void 0===startSide)break;const connectedPoints=[],startPoint=startSide[0];for(;;){connectedPoints.push(startSide[0]);const nextPoint=startSide[1];if(nextPoint===startPoint)break;const nextPossibleSides=pointMap.get(nextPoint);if(!nextPossibleSides)throw new Error(`geometry is not closed at point ${nextPoint}`);const nextSide=popNextSide(startSide,nextPossibleSides);0===nextPossibleSides.length&&pointMap.delete(nextPoint),startSide=nextSide}connectedPoints.length>0&&connectedPoints.push(connectedPoints.shift()),outlines.push(connectedPoints)}return pointMap.clear(),create$a(outlines)},fromCompactBinary:data=>{if(0!==data[0])throw new Error("invalid compact binary data");const created=create$a();created.transforms=clone$a(data.slice(1,17));for(let i=21;i<data.length;){const length=data[i++];if(length<0||i+2*length>data.length)throw new Error("invalid compact binary data");const outline=[];for(let j=0;j<length;j++){const x=data[i+2*j],y=data[i+2*j+1];outline.push(fromValues$2(x,y))}created.outlines.push(outline),i+=2*length}return data[17]>=0&&(created.color=[data[17],data[18],data[19],data[20]]),created},isA:isA$5,reverse:geometry=>{const outlines=toOutlines(geometry).map((outline=>outline.slice().reverse())),reversed=create$a(outlines);return geometry.color&&(reversed.color=geometry.color),reversed},toOutlines:toOutlines,toPoints:geometry=>{const points=[];return toOutlines(geometry).forEach((outline=>{outline.forEach((point=>{points.push(point)}))})),points},toSides:geometry=>{const sides=[];return toOutlines(geometry).forEach((outline=>{outline.forEach(((point,i)=>{const j=(i+1)%outline.length;sides.push([point,outline[j]])}))})),sides},toString:geometry=>{const outlines=toOutlines(geometry);let result="geom2 ("+outlines.length+" outlines):\n[\n";return outlines.forEach((outline=>{result+=" ["+outline.map(toString$9).join()+"]\n"})),result+="]\n",result},toCompactBinary:geometry=>{const transforms=geometry.transforms;let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);let size=21;geometry.outlines.forEach((outline=>{size+=2*outline.length+1}));const compacted=new Float32Array(size);compacted[0]=0,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=color[0],compacted[18]=color[1],compacted[19]=color[2],compacted[20]=color[3];let index=21;return geometry.outlines.forEach((outline=>{compacted[index++]=outline.length,outline.forEach((point=>{compacted[index++]=point[0],compacted[index++]=point[1]}))})),compacted},transform:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$5(object))throw new Error("invalid geom2 structure");if(object.outlines.forEach(((outline,i)=>{if(outline.length<3)throw new Error(`geom2 outline ${i} must contain at least 3 points`);for(let i=0;i<outline.length;i++){const j=(i+1)%outline.length;if(equals$6(outline[i],outline[j]))throw new Error(`geom2 outline ${i} has duplicate point ${outline[i]}`)}})),toOutlines(object).forEach(((outline,i)=>{for(let a1=0;a1<outline.length;a1++){const a2=(a1+1)%outline.length;for(let b1=0;b1<outline.length;b1++){const b2=(b1+1)%outline.length;if(a1!==b1){const int=intersect$1(outline[a1],outline[a2],outline[b1],outline[b2],!1);if(int)throw new Error(`geom2 outline ${i} self intersection at ${int}`)}}}})),!object.transforms.every(Number.isFinite))throw new Error(`geom2 invalid transforms ${object.transforms}`)}});const create$8=polygons=>(void 0===polygons&&(polygons=[]),{polygons:polygons,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),create$7=vertices=>((void 0===vertices||vertices.length<3)&&(vertices=[]),{vertices:vertices}),fromVerticesAndPlane=(vertices,plane)=>{const poly=create$7(vertices);return poly.plane=plane,poly},create$6=()=>[0,0,0,0],clone$5=vector=>{const out=[0,0,0,0];return out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out[3]=vector[3],out},copy$2=(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out[3]=vector[3],out),equals$5=(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3],flip=(out,plane)=>(out[0]=-plane[0],out[1]=-plane[1],out[2]=-plane[2],out[3]=-plane[3],out),fromValues$1=(x,y,z,w)=>{const out=[0,0,0,0];return out[0]=x,out[1]=y,out[2]=z,out[3]=w,out},fromPoints$4=(out,...vertices)=>{const len=vertices.length,ba=[0,0,0],ca=[0,0,0],vertexNormal=index=>{const a=vertices[index],b=vertices[(index+1)%len],c=vertices[(index+2)%len];return subtract$3(ba,b,a),subtract$3(ca,c,a),cross$1(ba,ba,ca),normalize$1(ba,ba),ba};return out[0]=0,out[1]=0,out[2]=0,3===len?copy$4(out,vertexNormal(0)):(vertices.forEach(((v,i)=>{add$1(out,out,vertexNormal(i))})),normalize$1(out,out)),out[3]=dot$2(out,vertices[0]),out},signedDistanceToPoint=(plane,point)=>dot$2(plane,point)-plane[3],toString$7=vec=>`(${vec[0].toFixed(9)}, ${vec[1].toFixed(9)}, ${vec[2].toFixed(9)}, ${vec[3].toFixed(9)})`;Object.freeze({__proto__:null,clone:clone$5,copy:copy$2,create:create$6,equals:equals$5,flip:flip,fromNormalAndPoint:(out,normal,point)=>{const u=normalize$1([0,0,0],normal),w=dot$2(point,u);return out[0]=u[0],out[1]=u[1],out[2]=u[2],out[3]=w,out},fromValues:fromValues$1,fromPoints:fromPoints$4,fromPointsRandom:(out,a,b,c)=>{let ba=subtract$3([0,0,0],b,a),ca=subtract$3([0,0,0],c,a);length$2(ba)<EPS&&(ba=orthogonal(ba,ca)),length$2(ca)<EPS&&(ca=orthogonal(ca,ba));let normal=cross$1([0,0,0],ba,ca);length$2(normal)<EPS&&(ca=orthogonal(ca,ba),normal=cross$1(normal,ba,ca)),normal=normalize$1(normal,normal);const w=dot$2(normal,a);return out[0]=normal[0],out[1]=normal[1],out[2]=normal[2],out[3]=w,out},projectionOfPoint:(plane,point)=>{const a=point[0]*plane[0]+point[1]*plane[1]+point[2]*plane[2]-plane[3],x=point[0]-a*plane[0],y=point[1]-a*plane[1],z=point[2]-a*plane[2];return fromValues$3(x,y,z)},signedDistanceToPoint:signedDistanceToPoint,toString:toString$7,transform:(out,plane,matrix)=>{const isMirror=isMirroring(matrix),r=orthogonal([0,0,0],plane),u=cross$1(r,plane,r),v=cross$1([0,0,0],plane,u);let point1=fromScalar$2([0,0,0],plane[3]);multiply$2(point1,point1,plane);let point2=add$1([0,0,0],point1,u),point3=add$1([0,0,0],point1,v);return point1=transform$c(point1,point1,matrix),point2=transform$c(point2,point2,matrix),point3=transform$c(point3,point3,matrix),fromPoints$4(out,point1,point2,point3),isMirror&&flip(out,out),out}});const invert$1=polygon=>{const vertices=polygon.vertices.slice().reverse(),inverted=create$7(vertices);return polygon.plane&&(inverted.plane=flip([0,0,0,0],polygon.plane)),inverted},isA$4=object=>!!(object&&"object"==typeof object&&"vertices"in object&&Array.isArray(object.vertices)),isConvex$1=polygon=>areVerticesConvex(polygon.vertices),areVerticesConvex=vertices=>{const numVertices=vertices.length;if(numVertices>2){const normal=fromPoints$4([0,0,0,0],...vertices);let prevPrevPos=vertices[numVertices-2],prevPos=vertices[numVertices-1];for(let i=0;i<numVertices;i++){const pos=vertices[i];if(!isConvexVertex(prevPrevPos,prevPos,pos,normal))return!1;prevPrevPos=prevPos,prevPos=pos}}return!0},isConvexVertex=(prevVertex,vertex,nextVertex,normal)=>{const crossProduct=cross$1([0,0,0],subtract$3([0,0,0],vertex,prevVertex),subtract$3([0,0,0],nextVertex,vertex));return dot$2(crossProduct,normal)>=0},plane=polygon=>(polygon.plane||(polygon.plane=fromPoints$4([0,0,0,0],...polygon.vertices)),polygon.plane),measureArea$2=polygon=>{const n=polygon.vertices.length;if(n<3)return 0;const vertices=polygon.vertices,normal=plane(polygon),ax=Math.abs(normal[0]),ay=Math.abs(normal[1]),az=Math.abs(normal[2]);if(ax+ay+az===0)return 0;let coord=3;ax>ay&&ax>az?coord=1:ay>az&&(coord=2);let area=0,h=0,i=1,j=2;switch(coord){case 1:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][1]*(vertices[j][2]-vertices[h][2]);area+=vertices[0][1]*(vertices[1][2]-vertices[n-1][2]),area/=2*normal[0];break;case 2:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][2]*(vertices[j][0]-vertices[h][0]);area+=vertices[0][2]*(vertices[1][0]-vertices[n-1][0]),area/=2*normal[1];break;default:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][0]*(vertices[j][1]-vertices[h][1]);area+=vertices[0][0]*(vertices[1][1]-vertices[n-1][1]),area/=2*normal[2]}return area};Object.freeze({__proto__:null,clone:clone$5,copy:copy$2,create:create$6,dot:(a,b)=>a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3],equals:equals$5,fromScalar:(out,scalar)=>(out[0]=scalar,out[1]=scalar,out[2]=scalar,out[3]=scalar,out),fromValues:fromValues$1,toString:toString$7,transform:(out,vector,matrix)=>{const[x,y,z,w]=vector;return out[0]=matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12]*w,out[1]=matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13]*w,out[2]=matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14]*w,out[3]=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15]*w,out}});const cache$4=new WeakMap,toVertices$1=polygon=>polygon.vertices,toString$6=polygon=>`poly3: [${polygon.vertices.map(toString$b).join(", ")}]`,transform$7=(matrix,polygon)=>{const vertices=polygon.vertices.map((vertex=>transform$c([0,0,0],vertex,matrix)));return isMirroring(matrix)&&vertices.reverse(),create$7(vertices)},validate$4=object=>{if(!isA$4(object))throw new Error("invalid poly3 structure");if(object.vertices.length<3)throw new Error(`poly3 not enough vertices ${object.vertices.length}`);if(measureArea$2(object)<=0)throw new Error("poly3 area must be greater than zero");for(let i=0;i<object.vertices.length;i++)if(equals$7(object.vertices[i],object.vertices[(i+1)%object.vertices.length]))throw new Error(`poly3 has duplicate vertex ${object.vertices[i]}`);if(!isConvex$1(object))throw new Error("poly3 must be convex");if(object.vertices.forEach((vertex=>{if(!vertex.every(Number.isFinite))throw new Error(`poly3 invalid vertex ${vertex}`)})),object.vertices.length>3){const normal=plane(object);object.vertices.forEach((vertex=>{const dist=Math.abs(signedDistanceToPoint(normal,vertex));if(dist>1e-13)throw new Error(`poly3 must be coplanar: vertex ${vertex} distance ${dist}`)}))}};Object.freeze({__proto__:null,clone:(...params)=>{let out,poly3;return 1===params.length?(out=create$7(),poly3=params[0]):(out=params[0],poly3=params[1]),out.vertices=poly3.vertices.map((vec=>clone$9(vec))),out},create:create$7,fromVerticesAndPlane:fromVerticesAndPlane,invert:invert$1,isA:isA$4,isConvex:isConvex$1,measureArea:measureArea$2,measureBoundingBox:polygon=>{const vertices=polygon.vertices,numVertices=vertices.length,min=0===numVertices?[0,0,0]:clone$9(vertices[0]),max=clone$9(min);for(let i=1;i<numVertices;i++)min$2(min,min,vertices[i]),max$2(max,max,vertices[i]);return[min,max]},measureBoundingSphere:polygon=>{const boundingSphere=cache$4.get(polygon);if(boundingSphere)return boundingSphere;const vertices=polygon.vertices,out=[0,0,0,0];if(0===vertices.length)return out[0]=0,out[1]=0,out[2]=0,out[3]=0,out;let minx=vertices[0],miny=minx,minz=minx,maxx=minx,maxy=minx,maxz=minx;vertices.forEach((v=>{minx[0]>v[0]&&(minx=v),miny[1]>v[1]&&(miny=v),minz[2]>v[2]&&(minz=v),maxx[0]<v[0]&&(maxx=v),maxy[1]<v[1]&&(maxy=v),maxz[2]<v[2]&&(maxz=v)})),out[0]=.5*(minx[0]+maxx[0]),out[1]=.5*(miny[1]+maxy[1]),out[2]=.5*(minz[2]+maxz[2]);const x=out[0]-maxx[0],y=out[1]-maxy[1],z=out[2]-maxz[2];return out[3]=Math.sqrt(x*x+y*y+z*z),cache$4.set(polygon,out),out},measureSignedVolume:polygon=>{let signedVolume=0;const vertices=polygon.vertices,cross=[0,0,0];for(let i=0;i<vertices.length-2;i++)cross$1(cross,vertices[i+1],vertices[i+2]),signedVolume+=dot$2(vertices[0],cross);return signedVolume/=6,signedVolume},plane:plane,toVertices:toVertices$1,toString:toString$6,transform:transform$7,validate:validate$4});const toPolygons$1=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.polygons=geometry.polygons.map((polygon=>transform$7(geometry.transforms,polygon))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).polygons,isA$3=object=>!!(object&&"object"==typeof object&&"polygons"in object&&"transforms"in object&&Array.isArray(object.polygons)&&"length"in object.transforms);Object.freeze({__proto__:null,clone:geometry=>Object.assign({},geometry),create:create$8,fromPoints:listOfLists=>{if(!Array.isArray(listOfLists))throw new Error("the given vertices must be an array");return create$8(listOfLists.map(create$7))},fromCompactBinary:data=>{if(1!==data[0])throw new Error("invalid compact binary data");const created=create$8();created.transforms=clone$a(data.slice(1,17));const numberOfVertices=data[21];let ci=22,vi=data.length-3*numberOfVertices;for(;vi<data.length;){const verticesPerPolygon=data[ci];ci++;const vertices=[];for(let i=0;i<verticesPerPolygon;i++)vertices.push(fromValues$3(data[vi],data[vi+1],data[vi+2])),vi+=3;created.polygons.push(create$7(vertices))}return data[17]>=0&&(created.color=[data[17],data[18],data[19],data[20]]),created},invert:geometry=>{const newPolygons=toPolygons$1(geometry).map((polygon=>invert$1(polygon)));return create$8(newPolygons)},isA:isA$3,toPoints:geometry=>toPolygons$1(geometry).map((polygon=>toVertices$1(polygon))),toPolygons:toPolygons$1,toString:geometry=>{const polygons=toPolygons$1(geometry);let result="geom3 ("+polygons.length+" polygons):\n";return polygons.forEach((polygon=>{result+=" "+toString$6(polygon)+"\n"})),result},toCompactBinary:geometry=>{const polygons=geometry.polygons,transforms=geometry.transforms,numberOfPolygons=polygons.length,numberOfVertices=polygons.reduce(((count,polygon)=>count+polygon.vertices.length),0);let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);const compacted=new Float32Array(22+numberOfPolygons+3*numberOfVertices);compacted[0]=1,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=color[0],compacted[18]=color[1],compacted[19]=color[2],compacted[20]=color[3],compacted[21]=numberOfVertices;let ci=22,vi=ci+numberOfPolygons;return polygons.forEach((polygon=>{const vertices=toVertices$1(polygon);compacted[ci]=vertices.length,ci++;for(let i=0;i<vertices.length;i++){const vertex=vertices[i];compacted[vi+0]=vertex[0],compacted[vi+1]=vertex[1],compacted[vi+2]=vertex[2],vi+=3}})),compacted},transform:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$3(object))throw new Error("invalid geom3 structure");if(object.polygons.forEach(validate$4),(object=>{const edgeCount=new Map;object.polygons.forEach((({vertices:vertices})=>{vertices.forEach(((v,i)=>{const edge=`${v}/${vertices[(i+1)%vertices.length]}`,count=edgeCount.has(edge)?edgeCount.get(edge):0;edgeCount.set(edge,count+1)}))}));const nonManifold=[];if(edgeCount.forEach(((count,edge)=>{const complementEdge=edge.split("/").reverse().join("/");count!==edgeCount.get(complementEdge)&&nonManifold.push(edge.replace("/"," -> "))})),nonManifold.length>0)throw new Error(`non-manifold edges ${nonManifold.length}\n${nonManifold.join("\n")}`)})(object),!object.transforms.every(Number.isFinite))throw new Error(`geom3 invalid transforms ${object.transforms}`)}});const clone$4=geometry=>Object.assign({},geometry),close=geometry=>{if(geometry.isClosed)return geometry;const cloned=clone$4(geometry);if(cloned.isClosed=!0,cloned.points.length>1){const points=cloned.points,p0=points[0];let pn=points[points.length-1];for(;distance(p0,pn)<EPS*EPS&&(points.pop(),1!==points.length);)pn=points[points.length-1]}return cloned},create$5=points=>(void 0===points&&(points=[]),{points:points,isClosed:!1,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),fromPoints$2=(options,points)=>{let{closed:closed}=Object.assign({},{closed:!1},options),created=create$5();if(created.points=points.map((point=>clone$8(point))),created.points.length>1){const p0=created.points[0],pn=created.points[created.points.length-1];distance(p0,pn)<EPS*EPS&&(closed=!0)}return!0===closed&&(created=close(created)),created},toPoints$1=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.points=geometry.points.map((point=>transform$b([0,0],point,geometry.transforms))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).points,concat=(...paths)=>{let isClosed=!1,newPoints=[];return paths.forEach(((path,i)=>{const tmp=toPoints$1(path).slice();if(newPoints.length>0&&tmp.length>0&&equals$6(tmp[0],newPoints[newPoints.length-1])&&tmp.shift(),tmp.length>0&&isClosed)throw new Error(`Cannot concatenate to a closed path; check the ${i}th path`);isClosed=path.isClosed,newPoints=newPoints.concat(tmp)})),fromPoints$2({closed:isClosed},newPoints)},appendPoints=(points,geometry)=>concat(geometry,create$5(points)),isA$2=object=>!!(object&&"object"==typeof object&&"points"in object&&"transforms"in object&&"isClosed"in object&&Array.isArray(object.points)&&"length"in object.transforms);Object.freeze({__proto__:null,appendArc:(options,geometry)=>{let{endpoint:endpoint,radius:radius,xaxisRotation:xaxisRotation,clockwise:clockwise,large:large,segments:segments}=Object.assign({},{radius:[0,0],xaxisRotation:0,clockwise:!1,large:!1,segments:16},options);if(!Array.isArray(endpoint))throw new Error("endpoint must be an array of X and Y values");if(endpoint.length<2)throw new Error("endpoint must contain X and Y values");if(endpoint=clone$8(endpoint),!Array.isArray(radius))throw new Error("radius must be an array of X and Y values");if(radius.length<2)throw new Error("radius must contain X and Y values");if(segments<4)throw new Error("segments must be four or more");if(geometry.isClosed)throw new Error("the given path cannot be closed");const points=toPoints$1(geometry);if(points.length<1)throw new Error("the given path must contain one or more points (as the starting point for the arc)");let xRadius=radius[0],yRadius=radius[1];const startpoint=points[points.length-1];xRadius=Math.round(1e5*xRadius)/1e5,yRadius=Math.round(1e5*yRadius)/1e5,endpoint=fromValues$2(Math.round(1e5*endpoint[0])/1e5,Math.round(1e5*endpoint[1])/1e5);const sweepFlag=!clockwise;let newPoints=[];if(0===xRadius||0===yRadius)newPoints.push(endpoint);else{xRadius=Math.abs(xRadius),yRadius=Math.abs(yRadius);const phi=xaxisRotation,cosPhi=Math.cos(phi),sinPhi=Math.sin(phi),minusHalfDistance=subtract$1([0,0],startpoint,endpoint);scale$1(minusHalfDistance,minusHalfDistance,.5);const x=Math.round(1e5*(cosPhi*minusHalfDistance[0]+sinPhi*minusHalfDistance[1]))/1e5,y=Math.round(1e5*(-sinPhi*minusHalfDistance[0]+cosPhi*minusHalfDistance[1]))/1e5,startTranslated=fromValues$2(x,y),bigLambda=startTranslated[0]*startTranslated[0]/(xRadius*xRadius)+startTranslated[1]*startTranslated[1]/(yRadius*yRadius);if(bigLambda>1){const sqrtBigLambda=Math.sqrt(bigLambda);xRadius*=sqrtBigLambda,yRadius*=sqrtBigLambda,xRadius=Math.round(1e5*xRadius)/1e5,yRadius=Math.round(1e5*yRadius)/1e5}let multiplier1=Math.sqrt((xRadius*xRadius*yRadius*yRadius-xRadius*xRadius*startTranslated[1]*startTranslated[1]-yRadius*yRadius*startTranslated[0]*startTranslated[0])/(xRadius*xRadius*startTranslated[1]*startTranslated[1]+yRadius*yRadius*startTranslated[0]*startTranslated[0]));sweepFlag===large&&(multiplier1=-multiplier1);const centerTranslated=fromValues$2(xRadius*startTranslated[1]/yRadius,-yRadius*startTranslated[0]/xRadius);scale$1(centerTranslated,centerTranslated,multiplier1);let center=fromValues$2(cosPhi*centerTranslated[0]-sinPhi*centerTranslated[1],sinPhi*centerTranslated[0]+cosPhi*centerTranslated[1]);center=add(center,center,scale$1([0,0],add([0,0],startpoint,endpoint),.5));const vector1=fromValues$2((startTranslated[0]-centerTranslated[0])/xRadius,(startTranslated[1]-centerTranslated[1])/yRadius),vector2=fromValues$2((-startTranslated[0]-centerTranslated[0])/xRadius,(-startTranslated[1]-centerTranslated[1])/yRadius),theta1=angleRadians(vector1);let deltatheta=angleRadians(vector2)-theta1;deltatheta%=TAU,!sweepFlag&&deltatheta>0?deltatheta-=TAU:sweepFlag&&deltatheta<0&&(deltatheta+=TAU);let numSteps=Math.ceil(Math.abs(deltatheta)/TAU*segments)+1;numSteps<1&&(numSteps=1);for(let step=1;step<numSteps;step++){const theta=theta1+step/numSteps*deltatheta,cosTheta=Math.cos(theta),sinTheta=Math.sin(theta),point=fromValues$2(cosPhi*xRadius*cosTheta-sinPhi*yRadius*sinTheta,sinPhi*xRadius*cosTheta+cosPhi*yRadius*sinTheta);add(point,point,center),newPoints.push(point)}numSteps&&newPoints.push(options.endpoint)}return newPoints=points.concat(newPoints),fromPoints$2({},newPoints)},appendBezier:(options,geometry)=>{let{controlPoints:controlPoints,segments:segments}=Object.assign({},{segments:16},options);if(!Array.isArray(controlPoints))throw new Error("controlPoints must be an array of one or more points");if(controlPoints.length<1)throw new Error("controlPoints must be an array of one or more points");if(segments<4)throw new Error("segments must be four or more");if(geometry.isClosed)throw new Error("the given geometry cannot be closed");const points=toPoints$1(geometry);if(points.length<1)throw new Error("the given path must contain one or more points (as the starting point for the bezier curve)");if(controlPoints=controlPoints.slice(),null===controlPoints[0]){if(controlPoints.length<2)throw new Error("a null control point must be passed with one more control points");let lastBezierControlPoint=points[points.length-2];if("lastBezierControlPoint"in geometry&&(lastBezierControlPoint=geometry.lastBezierControlPoint),!Array.isArray(lastBezierControlPoint))throw new Error("the given path must contain TWO or more points if given a null control point");const controlPoint=scale$1([0,0],points[points.length-1],2);subtract$1(controlPoint,controlPoint,lastBezierControlPoint),controlPoints[0]=controlPoint}controlPoints.unshift(points[points.length-1]);const bezierOrder=controlPoints.length-1,factorials=[];let fact=1;for(let i=0;i<=bezierOrder;++i)i>0&&(fact*=i),factorials.push(fact);const binomials=[];for(let i=0;i<=bezierOrder;++i){const binomial=factorials[bezierOrder]/(factorials[i]*factorials[bezierOrder-i]);binomials.push(binomial)}const v0=[0,0],v1=[0,0],v3=[0,0,0],getPointForT=t=>{let tk=1,oneMinusTNMinusK=Math.pow(1-t,bezierOrder);const invOneMinusT=1!==t?1/(1-t):1,point=[0,0];for(let k=0;k<=bezierOrder;++k){k===bezierOrder&&(oneMinusTNMinusK=1);const bernsteinCoefficient=binomials[k]*tk*oneMinusTNMinusK,derivativePoint=scale$1(v0,controlPoints[k],bernsteinCoefficient);add(point,point,derivativePoint),tk*=t,oneMinusTNMinusK*=invOneMinusT}return point},newPoints=[],newPointsT=[],numSteps=bezierOrder+1;for(let i=0;i<numSteps;++i){const t=i/(numSteps-1),point=getPointForT(t);newPoints.push(point),newPointsT.push(t)}let subdivideBase=1;const maxAngle=TAU/segments,maxSinAngle=Math.sin(maxAngle);for(;subdivideBase<newPoints.length-1;){const dir1=subtract$1(v0,newPoints[subdivideBase],newPoints[subdivideBase-1]);normalize(dir1,dir1);const dir2=subtract$1(v1,newPoints[subdivideBase+1],newPoints[subdivideBase]);normalize(dir2,dir2);const sinAngle=cross(v3,dir1,dir2);if(Math.abs(sinAngle[2])>maxSinAngle){const t0=newPointsT[subdivideBase-1],t1=newPointsT[subdivideBase+1],newt0=t0+1*(t1-t0)/3,newt1=t0+2*(t1-t0)/3,point0=getPointForT(newt0),point1=getPointForT(newt1);newPoints.splice(subdivideBase,1,point0,point1),newPointsT.splice(subdivideBase,1,newt0,newt1),subdivideBase--,subdivideBase<1&&(subdivideBase=1)}else++subdivideBase}newPoints.shift();const result=appendPoints(newPoints,geometry);return result.lastBezierControlPoint=controlPoints[controlPoints.length-2],result},appendPoints:appendPoints,clone:clone$4,close:close,concat:concat,create:create$5,equals:(a,b)=>{if(a.isClosed!==b.isClosed)return!1;if(a.points.length!==b.points.length)return!1;const aPoints=toPoints$1(a),bPoints=toPoints$1(b),length=aPoints.length;let offset=0;do{let unequal=!1;for(let i=0;i<length;i++)if(!equals$6(aPoints[i],bPoints[(i+offset)%length])){unequal=!0;break}if(!1===unequal)return!0;if(!a.isClosed)return!1}while(++offset<length);return!1},fromPoints:fromPoints$2,fromCompactBinary:data=>{if(2!==data[0])throw new Error("invalid compact binary data");const created=create$5();created.transforms=clone$a(data.slice(1,17)),created.isClosed=!!data[17];for(let i=22;i<data.length;i+=2){const point=fromValues$2(data[i],data[i+1]);created.points.push(point)}return data[18]>=0&&(created.color=[data[18],data[19],data[20],data[21]]),created},isA:isA$2,reverse:geometry=>{const cloned=clone$4(geometry);return cloned.points=geometry.points.slice().reverse(),cloned},toPoints:toPoints$1,toString:geometry=>{const points=toPoints$1(geometry);let result="path ("+points.length+" points, "+geometry.isClosed+"):\n[\n";return points.forEach((point=>{result+=" "+toString$9(point)+",\n"})),result+="]\n",result},toCompactBinary:geometry=>{const points=geometry.points,transforms=geometry.transforms;let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);const compacted=new Float32Array(22+2*points.length);compacted[0]=2,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=geometry.isClosed?1:0,compacted[18]=color[0],compacted[19]=color[1],compacted[20]=color[2],compacted[21]=color[3];for(let j=0;j<points.length;j++){const ci=2*j+22,point=points[j];compacted[ci]=point[0],compacted[ci+1]=point[1]}return compacted},transform:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$2(object))throw new Error("invalid path2 structure");if(object.points.length>1)for(let i=0;i<object.points.length;i++)if(equals$6(object.points[i],object.points[(i+1)%object.points.length]))throw new Error(`path2 has duplicate point ${object.points[i]}`);if(object.points.forEach((point=>{if(!point.every(Number.isFinite))throw new Error(`path2 invalid point ${point}`)})),!object.transforms.every(Number.isFinite))throw new Error(`path2 invalid transforms ${object.transforms}`)}});const getPermutations=function(c){const permutations=[];for(let i=0;i<=c;i++)permutations.push(factorial(c)/(factorial(i)*factorial(c-i)));return permutations},factorial=function(b){let out=1;for(let i=2;i<=b;i++)out*=i;return out},valueAt=(t,bezier)=>{if(t<0||t>1)throw new Error("Bezier valueAt() input must be between 0 and 1");if("float_single"===bezier.pointType)return bezierFunction(bezier,bezier.points,t);{const result=[];for(let i=0;i<bezier.dimensions;i++){const singleDimensionPoints=[];for(let j=0;j<bezier.points.length;j++)singleDimensionPoints.push(bezier.points[j][i]);result.push(bezierFunction(bezier,singleDimensionPoints,t))}return result}},bezierFunction=function(bezier,p,t){const n=p.length-1;let result=0;for(let i=0;i<=n;i++)result+=bezier.permutations[i]*Math.pow(1-t,n-i)*Math.pow(t,i)*p[i];return result},bezierTangent=function(bezier,p,t){const n=p.length-1;let result=0;for(let i=0;i<n;i++){const q=n*(p[i+1]-p[i]);result+=bezier.tangentPermutations[i]*Math.pow(1-t,n-1-i)*Math.pow(t,i)*q}return result},lengths=(segments,bezier)=>{let sum=0;const lengths=[0];let previous=valueAt(0,bezier);for(let index=1;index<=segments;index++){const current=valueAt(index/segments,bezier);sum+=distanceBetween(current,previous),lengths.push(sum),previous=current}return lengths},distanceBetween=(a,b)=>{if(Number.isFinite(a)&&Number.isFinite(b))return Math.abs(a-b);if(Array.isArray(a)&&Array.isArray(b)){if(a.length!==b.length)throw new Error("The operands must have the same number of dimensions.");let sum=0;for(let i=0;i<a.length;i++)sum+=(b[i]-a[i])*(b[i]-a[i]);return Math.sqrt(sum)}throw new Error("The operands must be of the same type, either number or array.")};Object.freeze({__proto__:null,create:points=>{if(!Array.isArray(points))throw new Error("Bezier points must be a valid array/");if(points.length<2)throw new Error("Bezier points must contain at least 2 values.");const pointType=function(points){let firstPointType=null;return points.forEach((point=>{let pType="";if(Number.isFinite(point))pType="float_single";else{if(!Array.isArray(point))throw new Error("Bezier points must all be numbers or arrays of number.");point.forEach((val=>{if(!Number.isFinite(val))throw new Error("Bezier point values must all be numbers.")})),pType="float_"+point.length}if(null==firstPointType)firstPointType=pType;else if(firstPointType!==pType)throw new Error("Bezier points must be either all numbers or all arrays of numbers of the same size.")})),firstPointType}(points);return{points:points,pointType:pointType,dimensions:"float_single"===pointType?0:points[0].length,permutations:getPermutations(points.length-1),tangentPermutations:getPermutations(points.length-2)}},valueAt:valueAt,tangentAt:(t,bezier)=>{if(t<0||t>1)throw new Error("Bezier tangentAt() input must be between 0 and 1");if("float_single"===bezier.pointType)return bezierTangent(bezier,bezier.points,t);{const result=[];for(let i=0;i<bezier.dimensions;i++){const singleDimensionPoints=[];for(let j=0;j<bezier.points.length;j++)singleDimensionPoints.push(bezier.points[j][i]);result.push(bezierTangent(bezier,singleDimensionPoints,t))}return result}},lengths:lengths,length:(segments,bezier)=>lengths(segments,bezier)[segments],arcLengthToT:(options,bezier)=>{const{distance:distance,segments:segments}=Object.assign({},{distance:0,segments:100},options),arcLengths=lengths(segments,bezier);let startIndex=0,endIndex=segments;for(;startIndex<=endIndex;){const middleIndex=Math.floor(startIndex+(endIndex-startIndex)/2),diff=arcLengths[middleIndex]-distance;if(diff<0)startIndex=middleIndex+1;else{if(!(diff>0)){endIndex=middleIndex;break}endIndex=middleIndex-1}}const targetIndex=endIndex;if(arcLengths[targetIndex]===distance)return targetIndex/segments;const lengthBefore=arcLengths[targetIndex];return(targetIndex+(distance-lengthBefore)/(arcLengths[targetIndex+1]-lengthBefore))/segments}});const area$1=points=>{let area=0;for(let i=0;i<points.length;i++){const j=(i+1)%points.length;area+=points[i][0]*points[j][1],area-=points[j][0]*points[i][1]}return area/2},measureArea$1=polygon=>area$1(polygon.points),create$3=points=>((void 0===points||points.length<3)&&(points=[]),{points:points}),reverse$3=polygon=>{const points=polygon.points.slice().reverse();return create$3(points)},arePointsInside=(points,polygon)=>0===points.length||polygon.points.length<3?0:(measureArea$1(polygon)<0&&(polygon=reverse$3(polygon)),points.reduce(((acc,point)=>acc+isPointInside(point,polygon.points)),0)===points.length?1:0),isPointInside=(point,polygon)=>{const numPoints=polygon.length,tx=point[0],ty=point[1];let vtx0=polygon[numPoints-1],vtx1=polygon[0],yFlag0=vtx0[1]>ty,insideFlag=0,i=0;for(let j=numPoints+1;--j;){const yFlag1=vtx1[1]>ty;if(yFlag0!==yFlag1){const xFlag0=vtx0[0]>tx,xFlag1=vtx1[0]>tx;(xFlag0&&xFlag1||vtx1[0]-(vtx1[1]-ty)*(vtx0[0]-vtx1[0])/(vtx0[1]-vtx1[1])>=tx)&&(insideFlag=!insideFlag)}yFlag0=yFlag1,vtx0=vtx1,vtx1=polygon[++i]}return insideFlag},isA$1=object=>!!(object&&"object"==typeof object&&"points"in object&&Array.isArray(object.points)),crossBetweenSegments=(p1,p2,p3)=>{const X1=p2[0]-p1[0],Y1=p2[1]-p1[1],X2=p3[0]-p1[0];return X1*(p3[1]-p1[1])-Y1*X2};Object.freeze({__proto__:null,arePointsInside:arePointsInside,clone:polygon=>Object.assign({},polygon),create:create$3,isA:isA$1,isConvex:polygon=>{const numPoints=polygon.points.length;if(numPoints>2){const points=polygon.points;let prev=0,curr=0;for(let i=0;i<numPoints;i++)if(curr=crossBetweenSegments(points[i],points[(i+1)%numPoints],points[(i+2)%numPoints]),0!==curr){if(curr*prev<0)return!1;prev=curr}}return!0},isSimple:polygon=>{const numPoints=polygon.points.length;if(numPoints<3)return!1;if(3===numPoints)return!0;const points=polygon.points,found=new Set;if(points.forEach((v=>found.add(v.toString()))),found.size!==numPoints)return!1;for(let i=0;i<numPoints;i++)for(let j=i+2;j<numPoints;j++){const k=(j+1)%numPoints;if(i!==k){const s0=points[i],s1=points[(i+1)%numPoints],z0=points[j],z1=points[k];if(intersect$1(s0,s1,z0,z1))return!1}}return!0},measureArea:measureArea$1,measureBoundingBox:polygon=>{const points=polygon.points,numPoints=points.length,min=0===numPoints?[0,0]:clone$8(points[0]),max=clone$8(min);for(let i=1;i<numPoints;i++)min$1(min,min,points[i]),max$1(max,max,points[i]);return[min,max]},reverse:reverse$3,toPoints:polygon=>polygon.points,toString:polygon=>`poly2: [${polygon.points.map(toString$9).join(", ")}]`,transform:(matrix,polygon)=>{const points=polygon.points.map((point=>transform$b([0,0],point,matrix)));return isMirroring(matrix)&&points.reverse(),create$3(points)},validate:object=>{if(!isA$1(object))throw new Error("invalid poly2 structure");if(object.points.length<3)throw new Error(`poly2 not enough points ${object.points.length}`);if(measureArea$1(object)<=0)throw new Error("poly2 area must be greater than zero");for(let i=0;i<object.points.length;i++)if(equals$6(object.points[i],object.points[(i+1)%object.points.length]))throw new Error(`poly2 duplicate point at ${i}: [${object.points[i]}]`);object.points.forEach((point=>{if(2!==point.length)throw new Error(`poly2 invalid point ${point}`);if(!point.every(Number.isFinite))throw new Error(`poly2 invalid point ${point}`)}))}});const calculatePlane=slice=>{if(slice.contours.length<1)throw new Error("slices must have at least one contour to calculate a plane");const middle=[0,0,0];let n=0;slice.contours.forEach((contour=>{contour.forEach((vertex=>{add$1(middle,middle,vertex),n++}))})),scale$3(middle,middle,1/n);let farthestBefore,farthestVertex,farthestAfter,farthestContour=[],distance=0;slice.contours.forEach((contour=>{let prev=contour[contour.length-1];contour.forEach((vertex=>{if(!equals$7(prev,vertex)){const d=squaredDistance$1(middle,vertex);d>distance&&(farthestContour=contour,farthestBefore=prev,farthestVertex=vertex,distance=d)}prev=vertex}))}));let prev=farthestContour[farthestContour.length-1];for(let i=0;i<farthestContour.length;i++){const vertex=farthestContour[i];if(!equals$7(prev,vertex)&&equals$7(prev,farthestVertex)){farthestAfter=vertex;break}prev=vertex}return fromPoints$4([0,0,0,0],farthestBefore,farthestVertex,farthestAfter)},create$2=(contours=[])=>({contours:contours}),isA=object=>!!(object&&"object"==typeof object&&"contours"in object&&Array.isArray(object.contours));class Node$2{constructor(i,x,y){this.i=i,this.x=x,this.y=y,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}}const insertNode=(i,x,y,last)=>{const p=new Node$2(i,x,y);return last?(p.next=last.next,p.prev=last,last.next.prev=p,last.next=p):(p.prev=p,p.next=p),p},removeNode=p=>{p.next.prev=p.prev,p.prev.next=p.next,p.prevZ&&(p.prevZ.nextZ=p.nextZ),p.nextZ&&(p.nextZ.prevZ=p.prevZ)},pointInTriangle=(ax,ay,bx,by,cx,cy,px,py)=>(cx-px)*(ay-py)-(ax-px)*(cy-py)>=0&&(ax-px)*(by-py)-(bx-px)*(ay-py)>=0&&(bx-px)*(cy-py)-(cx-px)*(by-py)>=0,area=(p,q,r)=>(q.y-p.y)*(r.x-q.x)-(q.x-p.x)*(r.y-q.y),linkedPolygon=(data,start,end,dim,clockwise)=>{let last;if(clockwise===signedArea$1(data,start,end,dim)>0)for(let i=start;i<end;i+=dim)last=insertNode(i,data[i],data[i+1],last);else for(let i=end-dim;i>=start;i-=dim)last=insertNode(i,data[i],data[i+1],last);return last&&equals$2(last,last.next)&&(removeNode(last),last=last.next),last},filterPoints=(start,end)=>{if(!start)return start;end||(end=start);let again,p=start;do{if(again=!1,p.steiner||!equals$2(p,p.next)&&0!==area(p.prev,p,p.next))p=p.next;else{if(removeNode(p),p=end=p.prev,p===p.next)break;again=!0}}while(again||p!==end);return end},cureLocalIntersections=(start,triangles,dim)=>{let p=start;do{const a=p.prev,b=p.next.next;!equals$2(a,b)&&intersects(a,p,p.next,b)&&locallyInside(a,b)&&locallyInside(b,a)&&(triangles.push(a.i/dim),triangles.push(p.i/dim),triangles.push(b.i/dim),removeNode(p),removeNode(p.next),p=start=b),p=p.next}while(p!==start);return filterPoints(p)},locallyInside=(a,b)=>area(a.prev,a,a.next)<0?area(a,b,a.next)>=0&&area(a,a.prev,b)>=0:area(a,b,a.prev)<0||area(a,a.next,b)<0,splitPolygon=(a,b)=>{const a2=new Node$2(a.i,a.x,a.y),b2=new Node$2(b.i,b.x,b.y),an=a.next,bp=b.prev;return a.next=b,b.prev=a,a2.next=an,an.prev=a2,b2.next=a2,a2.prev=b2,bp.next=b2,b2.prev=bp,b2},isValidDiagonal=(a,b)=>a.next.i!==b.i&&a.prev.i!==b.i&&!((a,b)=>{let p=a;do{if(p.i!==a.i&&p.next.i!==a.i&&p.i!==b.i&&p.next.i!==b.i&&intersects(p,p.next,a,b))return!0;p=p.next}while(p!==a);return!1})(a,b)&&(locallyInside(a,b)&&locallyInside(b,a)&&((a,b)=>{let p=a,inside=!1;const px=(a.x+b.x)/2,py=(a.y+b.y)/2;do{p.y>py!=p.next.y>py&&p.next.y!==p.y&&px<(p.next.x-p.x)*(py-p.y)/(p.next.y-p.y)+p.x&&(inside=!inside),p=p.next}while(p!==a);return inside})(a,b)&&(area(a.prev,a,b.prev)||area(a,b.prev,b))||equals$2(a,b)&&area(a.prev,a,a.next)>0&&area(b.prev,b,b.next)>0),intersects=(p1,q1,p2,q2)=>{const o1=Math.sign(area(p1,q1,p2)),o2=Math.sign(area(p1,q1,q2)),o3=Math.sign(area(p2,q2,p1)),o4=Math.sign(area(p2,q2,q1));return o1!==o2&&o3!==o4||!(0!==o1||!onSegment(p1,p2,q1))||!(0!==o2||!onSegment(p1,q2,q1))||!(0!==o3||!onSegment(p2,p1,q2))||!(0!==o4||!onSegment(p2,q1,q2))},onSegment=(p,q,r)=>q.x<=Math.max(p.x,r.x)&&q.x>=Math.min(p.x,r.x)&&q.y<=Math.max(p.y,r.y)&&q.y>=Math.min(p.y,r.y),signedArea$1=(data,start,end,dim)=>{let sum=0;for(let i=start,j=end-dim;i<end;i+=dim)sum+=(data[j]-data[i])*(data[i+1]+data[j+1]),j=i;return sum},equals$2=(p1,p2)=>p1.x===p2.x&&p1.y===p2.y,eliminateHole=(hole,outerNode)=>{const bridge=findHoleBridge(hole,outerNode);if(!bridge)return outerNode;const bridgeReverse=splitPolygon(bridge,hole),filteredBridge=filterPoints(bridge,bridge.next);return filterPoints(bridgeReverse,bridgeReverse.next),outerNode===bridge?filteredBridge:outerNode},findHoleBridge=(hole,outerNode)=>{let p=outerNode;const hx=hole.x,hy=hole.y;let m,qx=-1/0;do{if(hy<=p.y&&hy>=p.next.y&&p.next.y!==p.y){const x=p.x+(hy-p.y)*(p.next.x-p.x)/(p.next.y-p.y);if(x<=hx&&x>qx){if(qx=x,x===hx){if(hy===p.y)return p;if(hy===p.next.y)return p.next}m=p.x<p.next.x?p:p.next}}p=p.next}while(p!==outerNode);if(!m)return null;if(hx===qx)return m;const stop=m,mx=m.x,my=m.y;let tanMin=1/0;p=m;do{if(hx>=p.x&&p.x>=mx&&hx!==p.x&&pointInTriangle(hy<my?hx:qx,hy,mx,my,hy<my?qx:hx,hy,p.x,p.y)){const tan=Math.abs(hy-p.y)/(hx-p.x);locallyInside(p,hole)&&(tan<tanMin||tan===tanMin&&(p.x>m.x||p.x===m.x&&sectorContainsSector(m,p)))&&(m=p,tanMin=tan)}p=p.next}while(p!==stop);return m},sectorContainsSector=(m,p)=>area(m.prev,m,p.prev)<0&&area(p.next,m,m.next)<0,getLeftmost=start=>{let p=start,leftmost=start;do{(p.x<leftmost.x||p.x===leftmost.x&&p.y<leftmost.y)&&(leftmost=p),p=p.next}while(p!==start);return leftmost},earcutLinked=(ear,triangles,dim,minX,minY,invSize,pass)=>{if(!ear)return;!pass&&invSize&&indexCurve(ear,minX,minY,invSize);let prev,next,stop=ear;for(;ear.prev!==ear.next;)if(prev=ear.prev,next=ear.next,invSize?isEarHashed(ear,minX,minY,invSize):isEar(ear))triangles.push(prev.i/dim),triangles.push(ear.i/dim),triangles.push(next.i/dim),removeNode(ear),ear=next.next,stop=next.next;else if((ear=next)===stop){pass?1===pass?(ear=cureLocalIntersections(filterPoints(ear),triangles,dim),earcutLinked(ear,triangles,dim,minX,minY,invSize,2)):2===pass&&splitEarcut(ear,triangles,dim,minX,minY,invSize):earcutLinked(filterPoints(ear),triangles,dim,minX,minY,invSize,1);break}},isEar=ear=>{const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;let p=ear.next.next;for(;p!==ear.prev;){if(pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.next}return!0},isEarHashed=(ear,minX,minY,invSize)=>{const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;const minTX=a.x<b.x?a.x<c.x?a.x:c.x:b.x<c.x?b.x:c.x,minTY=a.y<b.y?a.y<c.y?a.y:c.y:b.y<c.y?b.y:c.y,maxTX=a.x>b.x?a.x>c.x?a.x:c.x:b.x>c.x?b.x:c.x,maxTY=a.y>b.y?a.y>c.y?a.y:c.y:b.y>c.y?b.y:c.y,minZ=zOrder(minTX,minTY,minX,minY,invSize),maxZ=zOrder(maxTX,maxTY,minX,minY,invSize);let p=ear.prevZ,n=ear.nextZ;for(;p&&p.z>=minZ&&n&&n.z<=maxZ;){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}for(;p&&p.z>=minZ;){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;n&&n.z<=maxZ;){if(n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}return!0},splitEarcut=(start,triangles,dim,minX,minY,invSize)=>{let a=start;do{let b=a.next.next;for(;b!==a.prev;){if(a.i!==b.i&&isValidDiagonal(a,b)){let c=splitPolygon(a,b);return a=filterPoints(a,a.next),c=filterPoints(c,c.next),earcutLinked(a,triangles,dim,minX,minY,invSize),void earcutLinked(c,triangles,dim,minX,minY,invSize)}b=b.next}a=a.next}while(a!==start)},indexCurve=(start,minX,minY,invSize)=>{let p=start;do{null===p.z&&(p.z=zOrder(p.x,p.y,minX,minY,invSize)),p.prevZ=p.prev,p.nextZ=p.next,p=p.next}while(p!==start);p.prevZ.nextZ=null,p.prevZ=null,((list,fn)=>{let i,p,q,e,numMerges,inSize=1;do{p=list,list=null;let tail=null;for(numMerges=0;p;){numMerges++,q=p;let pSize=0;for(i=0;i<inSize&&(pSize++,q=q.nextZ,q);i++);let qSize=inSize;for(;pSize>0||qSize>0&&q;)0!==pSize&&(0===qSize||!q||fn(p)<=fn(q))?(e=p,p=p.nextZ,pSize--):(e=q,q=q.nextZ,qSize--),tail?tail.nextZ=e:list=e,e.prevZ=tail,tail=e;p=q}tail.nextZ=null,inSize*=2}while(numMerges>1)})(p,(p=>p.z))},zOrder=(x,y,minX,minY,invSize)=>(x=1431655765&((x=858993459&((x=252645135&((x=16711935&((x=32767*(x-minX)*invSize)|x<<8))|x<<4))|x<<2))|x<<1))|(y=1431655765&((y=858993459&((y=252645135&((y=16711935&((y=32767*(y-minY)*invSize)|y<<8))|y<<4))|y<<2))|y<<1))<<1;class PolygonHierarchy{constructor(slice){this.plane=calculatePlane(slice);const rightVector=orthogonal([0,0,0],this.plane),perp=cross$1([0,0,0],this.plane,rightVector);this.v=normalize$1(perp,perp),this.u=cross$1([0,0,0],this.v,this.plane),this.basisMap=new Map;const projected=slice.contours.map((part=>part.map((v=>this.to2D(v))))),geometry=create$a(projected);this.roots=(geometry=>{const outlines=toOutlines(geometry),solids=[],holes=[];outlines.forEach(((outline,i)=>{const a=area$1(outline);a<0?holes.push(i):a>0&&solids.push(i)}));const children=[],parents=[];return solids.forEach(((s,i)=>{const solid=outlines[s];children[i]=[],holes.forEach(((h,j)=>{const hole=outlines[h];arePointsInside([hole[0]],create$3(solid))&&(children[i].push(h),parents[j]||(parents[j]=[]),parents[j].push(i))}))})),holes.forEach(((h,j)=>{if(parents[j]&&parents[j].length>1){const directParent=((list,score)=>{let bestIndex,best;return list.forEach(((item,index)=>{const value=score(item);(void 0===best||value<best)&&(bestIndex=index,best=value)})),bestIndex})(parents[j],(p=>children[p].length));parents[j].forEach(((p,i)=>{i!==directParent&&(children[p]=children[p].filter((c=>c!==h)))}))}})),children.map(((holes,i)=>({solid:outlines[solids[i]],holes:holes.map((h=>outlines[h]))})))})(geometry)}to2D(vector3){const vector2=fromValues$2(dot$2(vector3,this.u),dot$2(vector3,this.v));return this.basisMap.set(vector2,vector3),vector2}to3D(vector2){const original=this.basisMap.get(vector2);if(original)return original;{console.log("Warning: point not in original slice");const v1=scale$3([0,0,0],this.u,vector2[0]),v2=scale$3([0,0,0],this.v,vector2[1]),planeOrigin=scale$3([0,0,0],this.plane,this.plane[3]),v3=add$1(v1,v1,planeOrigin);return add$1(v2,v2,v3)}}}Object.freeze({__proto__:null,calculatePlane:calculatePlane,clone:slice=>Object.assign({},slice),create:create$2,equals:(a,b)=>{if(a.contours.length!==b.contours.length)return!1;const len=a.contours.length;for(let i=0;i<len;i++){const aVertex=a.contours[i];for(let j=0;j<len;j++){const bVertex=b.contours[j];if(!equals$7(aVertex,bVertex))return!1}}return!0},fromGeom2:geometry=>{const contours=toOutlines(geometry).map((outline=>outline.map((point=>fromVec2([0,0,0],point)))));return create$2(contours)},fromVertices:vertices=>{if(!Array.isArray(vertices))throw new Error("the given vertices must be an array");if(vertices.length<3)throw new Error("the given vertices must contain THREE or more vertices");const cloned=vertices.map((vertex=>3===vertex.length?vertex:fromVec2([0,0,0],vertex)));return create$2([cloned])},isA:isA,reverse:slice=>{const contours=slice.contours.map((contour=>contour.slice().reverse()));return create$2(contours)},toEdges:slice=>{const edges=[];return slice.contours.forEach((contour=>{contour.forEach(((vertex,i)=>{const next=contour[(i+1)%contour.length];edges.push([vertex,next])}))})),edges},toVertices:slice=>{const vertices=[];return slice.contours.forEach((contour=>{contour.forEach((vertex=>{vertices.push(vertex)}))})),vertices},toPolygons:slice=>{const hierarchy=new PolygonHierarchy(slice),polygons=[];return hierarchy.roots.forEach((({solid:solid,holes:holes})=>{let index=solid.length;const holesIndex=[];holes.forEach(((hole,i)=>{holesIndex.push(index),index+=hole.length}));const vertices=[solid,...holes].flat(),getVertex=i=>hierarchy.to3D(vertices[i]),indices=((data,holeIndices,dim=2)=>{const hasHoles=holeIndices&&holeIndices.length,outerLen=hasHoles?holeIndices[0]*dim:data.length;let outerNode=linkedPolygon(data,0,outerLen,dim,!0);const triangles=[];if(!outerNode||outerNode.next===outerNode.prev)return triangles;let minX,minY,maxX,maxY,invSize;if(hasHoles&&(outerNode=((data,holeIndices,outerNode,dim)=>{const queue=[];for(let i=0,len=holeIndices.length;i<len;i++){const start=holeIndices[i]*dim,end=i<len-1?holeIndices[i+1]*dim:data.length,list=linkedPolygon(data,start,end,dim,!1);list===list.next&&(list.steiner=!0),queue.push(getLeftmost(list))}queue.sort(((a,b)=>a.x-b.x));for(let i=0;i<queue.length;i++)outerNode=eliminateHole(queue[i],outerNode),outerNode=filterPoints(outerNode,outerNode.next);return outerNode})(data,holeIndices,outerNode,dim)),data.length>80*dim){minX=maxX=data[0],minY=maxY=data[1];for(let i=dim;i<outerLen;i+=dim){const x=data[i],y=data[i+1];x<minX&&(minX=x),y<minY&&(minY=y),x>maxX&&(maxX=x),y>maxY&&(maxY=y)}invSize=Math.max(maxX-minX,maxY-minY),invSize=0!==invSize?1/invSize:0}return earcutLinked(outerNode,triangles,dim,minX,minY,invSize),triangles})(vertices.flat(),holesIndex);for(let i=0;i<indices.length;i+=3){const tri=indices.slice(i,i+3).map(getVertex);polygons.push(fromVerticesAndPlane(tri,hierarchy.plane))}})),polygons},toString:slice=>{let result="slice ("+slice.contours.length+" contours):\n[\n";return slice.contours.forEach((contour=>{result+=" ["+contour.map(toString$b).join()+"],\n"})),result+="]\n",result},transform:(matrix,slice)=>{const contours=slice.contours.map((contour=>contour.map((vertex=>transform$c([0,0,0],vertex,matrix)))));return create$2(contours)},validate:object=>{if(!isA(object))throw new Error("invalid slice structure");const slicePlane=calculatePlane(object);object.contours.forEach(((contour,i)=>{if(contour.length<3)throw new Error(`slice contour ${i} must contain at least 3 vertices`);const contourPlane=plane(create$7(contour));if(!equals$5(slicePlane,contourPlane))throw new Error("slice contours must be coplanar");for(let i=0;i<contour.length;i++){if(!contour[i].every(Number.isFinite))throw new Error(`slice contour ${i} must contain finite vertices`);const j=(i+1)%contour.length;if(equals$7(contour[i],contour[j]))throw new Error(`slice contour ${i} has duplicate vertex ${contour[i]}`)}}))}});const direction$1=line=>{const vector=normal([0,0],line);return negate(vector,vector),vector},origin$1=line=>scale$1([0,0],line,line[2]),copy$1=(out,line)=>(out[0]=line[0],out[1]=line[1],out[2]=line[2],out),fromPoints$1=(out,point1,point2)=>{const vector=subtract$1([0,0],point2,point1);normal(vector,vector),normalize(vector,vector);const distance=dot$1(point1,vector);return out[0]=vector[0],out[1]=vector[1],out[2]=distance,out},fromValues=(x,y,d)=>{const out=[0,1,0];return out[0]=x,out[1]=y,out[2]=d,out},solve2Linear=(a,b,c,d,u,v)=>{const invdet=1/(a*d-b*c);let x=u*d-b*v,y=-u*c+a*v;return x*=invdet,y*=invdet,[x,y]};Object.freeze({__proto__:null,clone:line=>{const out=[0,1,0];return out[0]=line[0],out[1]=line[1],out[2]=line[2],out},closestPoint:(line,point)=>{const orig=origin$1(line),dir=direction$1(line),v=subtract$1([0,0],point,orig),dist=dot$1(v,dir);return scale$1(v,dir,dist),add(v,v,orig),v},copy:copy$1,create:()=>[0,1,0],direction:direction$1,distanceToPoint:(line,point)=>{let distance=dot$1(point,line);return distance=Math.abs(distance-line[2]),distance},equals:(line1,line2)=>line1[0]===line2[0]&&line1[1]===line2[1]&&line1[2]===line2[2],fromPoints:fromPoints$1,fromValues:fromValues,intersectPointOfLines:(line1,line2)=>{const point=solve2Linear(line1[0],line1[1],line2[0],line2[1],line1[2],line2[2]);return clone$8(point)},origin:origin$1,reverse:(out,line)=>{const normal=negate([0,0],line),distance=-line[2];return copy$1(out,fromValues(normal[0],normal[1],distance))},toString:line=>`line2: (${line[0].toFixed(7)}, ${line[1].toFixed(7)}, ${line[2].toFixed(7)})`,transform:(out,line,matrix)=>{const org=origin$1(line),dir=direction$1(line);return transform$b(org,org,matrix),transform$b(dir,dir,matrix),fromPoints$1(out,org,dir)},xAtY:(line,y)=>{let x=(line[2]-line[1]*y)/line[0];return Number.isNaN(x)&&(x=origin$1(line)[0]),x}});const create=()=>[fromValues$3(0,0,0),fromValues$3(0,0,1)],closestPoint=(line,point)=>{const lPoint=line[0],lDirection=line[1],a=dot$2(subtract$3([0,0,0],point,lPoint),lDirection),b=dot$2(lDirection,lDirection),closestPoint=scale$3([0,0,0],lDirection,a/b);return add$1(closestPoint,closestPoint,lPoint),closestPoint},fromPointAndDirection=(out,point,direction)=>{const unit=normalize$1([0,0,0],direction);return copy$4(out[0],point),copy$4(out[1],unit),out};Object.freeze({__proto__:null,clone:line=>{const out=create();return copy$4(out[0],line[0]),copy$4(out[1],line[1]),out},closestPoint:closestPoint,copy:(out,line)=>(copy$4(out[0],line[0]),copy$4(out[1],line[1]),out),create:create,direction:line=>line[1],distanceToPoint:(line,point)=>{const closest=closestPoint(line,point),distanceVector=subtract$3([0,0,0],point,closest);return length$2(distanceVector)},equals:(line1,line2)=>!!equals$7(line1[1],line2[1])&&!!equals$7(line1[0],line2[0]),fromPlanes:(out,plane1,plane2)=>{let direction=cross$1([0,0,0],plane1,plane2),length=length$2(direction);if(length<EPS)throw new Error("parallel planes do not intersect");length=1/length,direction=scale$3(direction,direction,length);const absX=Math.abs(direction[0]),absY=Math.abs(direction[1]),absZ=Math.abs(direction[2]);let origin,r;return absX>=absY&&absX>=absZ?(r=solve2Linear(plane1[1],plane1[2],plane2[1],plane2[2],plane1[3],plane2[3]),origin=fromValues$3(0,r[0],r[1])):absY>=absX&&absY>=absZ?(r=solve2Linear(plane1[0],plane1[2],plane2[0],plane2[2],plane1[3],plane2[3]),origin=fromValues$3(r[0],0,r[1])):(r=solve2Linear(plane1[0],plane1[1],plane2[0],plane2[1],plane1[3],plane2[3]),origin=fromValues$3(r[0],r[1],0)),fromPointAndDirection(out,origin,direction)},fromPointAndDirection:fromPointAndDirection,fromPoints:(out,point1,point2)=>{const direction=subtract$3([0,0,0],point2,point1);return fromPointAndDirection(out,point1,direction)},intersectPointOfLineAndPlane:(line,plane)=>{const pNormal=plane,pw=plane[3],lPoint=line[0],lDirection=line[1],labda=(pw-dot$2(pNormal,lPoint))/dot$2(pNormal,lDirection);return add$1([0,0,0],lPoint,scale$3([0,0,0],lDirection,labda))},origin:line=>line[0],reverse:(out,line)=>{const point=clone$9(line[0]),direction=negate$1([0,0,0],line[1]);return fromPointAndDirection(out,point,direction)},toString:line=>{const point=line[0],direction=line[1];return`line3: point: (${point[0].toFixed(7)}, ${point[1].toFixed(7)}, ${point[2].toFixed(7)}) direction: (${direction[0].toFixed(7)}, ${direction[1].toFixed(7)}, ${direction[2].toFixed(7)})`},transform:(out,line,matrix)=>{const point=line[0],direction=line[1],pointPlusDirection=add$1([0,0,0],point,direction),newPoint=transform$c([0,0,0],point,matrix),newPointPlusDirection=transform$c(pointPlusDirection,pointPlusDirection,matrix),newDirection=subtract$3(newPointPlusDirection,newPointPlusDirection,newPoint);return fromPointAndDirection(out,newPoint,newDirection)}});const isNumberArray=(array,dimension)=>!!(Array.isArray(array)&&array.length>=dimension)&&array.every((n=>Number.isFinite(n))),getGroups=(data,options)=>{let groups=[];const positions=[];let material=null;groups.push({faces:[],colors:[],name:"default",line:0});const handleG=(command,values)=>{const group={faces:[],colors:[],name:""};values&&values.length>0&&(group.name=values.join(" ")),groups.push(group)},handleV=(command,values)=>{const x=parseFloat(values[0]),y=parseFloat(values[1]),z=parseFloat(values[2]);positions.push([x,y,z])},handleF=(command,values)=>{const facerefs=values.map((value=>{const refs=value.match(/[0-9+\-eE]+/g);let ref=parseInt(refs[0]);return ref<0?ref=positions.length+ref:ref--,ref})),group=groups.pop();group.faces.push(facerefs),group.colors.push(material),groups.push(group)},handleMtl=(command,values)=>{if(material=null,values&&values.length>0){const c=(s=values[0],cssColors[s.toLowerCase()]);c&&(material=[c[0],c[1],c[2],1])}var s},lines=data.split(/\n/);for(let i=0;i<lines.length;i++){const line=lines[i].trim();if(line&&line.length>0){let values=line.match(/\S+/g);if(values){const command=values[0];switch(values=values.slice(1),command){case"g":handleG(0,values);break;case"v":handleV(0,values);break;case"f":handleF(0,values);break;case"usemtl":handleMtl(0,values)}}}}return groups=groups.filter((group=>group.faces.length>0)),{positions:positions,groups:groups}},objectify=(points,groups,options)=>{const geometries=groups.map((group=>(options=>{const{points:points,faces:faces,colors:colors,orientation:orientation}=Object.assign({},{points:[],faces:[],colors:void 0,orientation:"outward"},options);if(!Array.isArray(points)||!Array.isArray(faces))throw new Error("points and faces must be arrays");if(points.length<3)throw new Error("three or more points are required");if(faces.length<1)throw new Error("one or more faces are required");if(colors){if(!Array.isArray(colors))throw new Error("colors must be an array");if(colors.length!==faces.length)throw new Error("faces and colors must have the same length")}points.forEach(((vertex,i)=>{if(!isNumberArray(vertex,3))throw new Error(`vertex ${i} must be an array of X, Y, Z values`)})),faces.forEach(((face,i)=>{if(face.length<3)throw new Error(`face ${i} must contain 3 or more indexes`);if(!isNumberArray(face,face.length))throw new Error(`face ${i} must be an array of numbers`)})),"outward"!==orientation&&faces.forEach((face=>face.reverse()));const polygons=faces.map(((face,findex)=>{const polygon=create$7(face.map((pindex=>points[pindex])));return colors&&colors[findex]&&(polygon.color=colors[findex]),polygon}));return create$8(polygons)})({orientation:options.orientation,points:points,faces:group.faces,colors:group.colors})));return geometries},stringify=(positions,groups,options)=>{const{filename:filename,addMetaData:addMetaData,version:version}=options;let code=addMetaData?`//\n// Produced by JSCAD IO Library : OBJ Deserializer (${version})\n// date: ${new Date}\n// source: ${filename}\n//\n `:"";return code+=`import * from '@jscad/modeling'\n\n// groups: ${groups.length}\n// points: ${positions.length}\nexport const main = () => {\n // points are common to all geometries\n${(points=>{let code=" let points = [\n";return points.forEach((point=>code+=` [${point}],\n`)),code+=" ]",code})(positions)}\n\n let geometries = [\n${(groups=>{let code="";return groups.forEach(((group,index)=>code+=` group${index}(points), // ${group.name}\n`)),code})(groups)} ]\n return geometries\n}\n\n${((groups,options)=>{let code="";return groups.forEach(((group,index)=>{const faces=group.faces,colors=group.colors;code+=`\n// group : ${group.name}\n// faces: ${faces.length}\n`,code+=`const group${index} = (points) => {\n${(faces=>{let code=" let faces = [\n";return faces.forEach((face=>code+=` [${face}],\n`)),code+=" ]",code})(faces)}\n${(colors=>{let code=" let colors = [\n";return colors.forEach((c=>{code+=c?` [${c}],\n`:" null,\n"})),code+=" ]",code})(colors)}\n return polyhedron({ orientation: '${options.orientation}', points, faces, colors })\n}\n`})),code})(groups,options)}\n`,code};exports.deserialize=(options,input)=>{const defaults={filename:"obj",output:"script",orientation:"outward",version:"3.0.0-alpha.0",addMetaData:!0};options=Object.assign({},defaults,options);const{output:output}=options;options&&options.statusCallback&&options.statusCallback({progress:0});const{positions:positions,groups:groups}=getGroups(input),result="script"===output?stringify(positions,groups,options):objectify(positions,groups,options);return options&&options.statusCallback&&options.statusCallback({progress:100}),result},exports.mimeType="model/obj",Object.defineProperty(exports,"__esModule",{value:!0})},"object"==typeof exports&&"undefined"!=typeof module?factory(exports):"function"==typeof define&&define.amd?define(["exports"],factory):factory((global="undefined"!=typeof globalThis?globalThis:global||self).jscadObjDeserializer={});
package/package.json CHANGED
@@ -1,26 +1,31 @@
1
1
  {
2
2
  "name": "@jscad/obj-deserializer",
3
- "version": "2.0.24",
3
+ "version": "3.0.0-alpha.0",
4
4
  "description": "OBJ Deserializer for JSCAD",
5
5
  "homepage": "https://openjscad.xyz/",
6
6
  "repository": "https://github.com/jscad/OpenJSCAD.org",
7
- "main": "index.js",
7
+ "type": "module",
8
+ "main": "src/index.js",
9
+ "unpkg": "dist/jscad-obj-deserializer.min.js",
10
+ "module": "dist/jscad-obj-deserializer.es.js",
8
11
  "scripts": {
9
- "coverage": "nyc --all --reporter=html --reporter=text npm test",
10
- "test": "ava --verbose --timeout 2m './tests/*.test.js'"
12
+ "build": "rollup --config",
13
+ "coverage": "c8 --all --reporter=html --reporter=text pnpm test",
14
+ "test": "ava --verbose --timeout 2m './tests/*.test.js'",
15
+ "version": "pnpm run build && git add dist"
11
16
  },
12
17
  "contributors": [
13
18
  {
14
19
  "name": "Rene K. Mueller",
15
- "url": "http://renekmueller.com"
20
+ "url": "https://github.com/Spiritdude"
16
21
  },
17
22
  {
18
23
  "name": "z3dev",
19
- "url": "http://www.z3d.jp"
24
+ "url": "https://github.com/z3dev"
20
25
  },
21
26
  {
22
27
  "name": "Mark 'kaosat-dev' Moissette",
23
- "url": "http://kaosat.net"
28
+ "url": "https://github.com/kaosat-dev"
24
29
  }
25
30
  ],
26
31
  "keywords": [
@@ -32,11 +37,16 @@
32
37
  ],
33
38
  "license": "MIT",
34
39
  "dependencies": {
35
- "@jscad/modeling": "2.11.1"
40
+ "@jscad/modeling": "3.0.0-alpha.0"
36
41
  },
37
42
  "devDependencies": {
38
- "ava": "3.15.0",
39
- "nyc": "15.1.0"
43
+ "@rollup/plugin-node-resolve": "^15.2.1",
44
+ "@rollup/plugin-terser": "^0.4.3",
45
+ "ava": "^4.3.3",
46
+ "c8": "^8.0.0",
47
+ "rollup": "^2.79.1",
48
+ "rollup-plugin-banner": "^0.2.1",
49
+ "rollup-plugin-version-injector": "^1.3.3"
40
50
  },
41
- "gitHead": "4313974b50957018d2edd010e3a251f59bea46a4"
51
+ "gitHead": "3656d36ed9cd738ab884e86aae5a2ce08d52adf7"
42
52
  }
@@ -0,0 +1,27 @@
1
+ import banner from 'rollup-plugin-banner'
2
+ import versionInjector from 'rollup-plugin-version-injector'
3
+ import { nodeResolve } from '@rollup/plugin-node-resolve'
4
+ import terser from '@rollup/plugin-terser'
5
+
6
+ export default {
7
+ input: 'src/index.js',
8
+
9
+ output: [
10
+ {
11
+ file: 'dist/jscad-obj-deserializer.min.js',
12
+ format: 'umd',
13
+ name: 'jscadObjDeserializer'
14
+ },
15
+ {
16
+ file: 'dist/jscad-obj-deserializer.es.js',
17
+ format: 'es'
18
+ }
19
+ ],
20
+
21
+ plugins: [
22
+ nodeResolve(),
23
+ banner('<%= pkg.description %>\n@module <%= pkg.name %>\n@version <%= pkg.version %>\n@license <%= pkg.license %>'),
24
+ versionInjector({ injectInComments: { fileRegexp: /\.(html)$/ }, logLevel: 'warn' }),
25
+ terser({ compress: { module: true }, mangle: false, format: { comments: 'some'} })
26
+ ]
27
+ }
@@ -1,6 +1,6 @@
1
- const { colors, primitives } = require('@jscad/modeling')
1
+ import { colorNameToRgb, polyhedron } from '@jscad/modeling'
2
2
 
3
- const version = require('./package.json').version
3
+ const version = '[VI]{version}[/VI]' // version is injected by rollup
4
4
 
5
5
  /**
6
6
  * Deserializer of OBJ data to JSCAD geometries.
@@ -85,7 +85,7 @@ const getGroups = (data, options) => {
85
85
  material = null
86
86
  if (values && values.length > 0) {
87
87
  // try to convert the material to a color by name
88
- const c = colors.colorNameToRgb(values[0])
88
+ const c = colorNameToRgb(values[0])
89
89
  if (c) material = [c[0], c[1], c[2], 1] // add alpha
90
90
  }
91
91
  }
@@ -124,7 +124,7 @@ const getGroups = (data, options) => {
124
124
  }
125
125
 
126
126
  const objectify = (points, groups, options) => {
127
- const geometries = groups.map((group) => primitives.polyhedron({ orientation: options.orientation, points, faces: group.faces, colors: group.colors }))
127
+ const geometries = groups.map((group) => polyhedron({ orientation: options.orientation, points, faces: group.faces, colors: group.colors }))
128
128
  return geometries
129
129
  }
130
130
 
@@ -173,7 +173,7 @@ const translateGroupsToFunctions = (groups, options) => {
173
173
  code += `const group${index} = (points) => {
174
174
  ${translateFaces(faces)}
175
175
  ${translateColors(colors)}
176
- return primitives.polyhedron({ orientation: '${options.orientation}', points, faces, colors })
176
+ return polyhedron({ orientation: '${options.orientation}', points, faces, colors })
177
177
  }
178
178
  `
179
179
  })
@@ -193,11 +193,11 @@ const stringify = (positions, groups, options) => {
193
193
  : ''
194
194
 
195
195
  // create the main function, with a list of points and translated groups
196
- code += `const {primitives} = require('@jscad/modeling')
196
+ code += `import * from '@jscad/modeling'
197
197
 
198
198
  // groups: ${groups.length}
199
199
  // points: ${positions.length}
200
- const main = () => {
200
+ export const main = () => {
201
201
  // points are common to all geometries
202
202
  ${translatePoints(positions)}
203
203
 
@@ -207,16 +207,15 @@ ${translateGroupsToCalls(groups)} ]
207
207
  }
208
208
 
209
209
  ${translateGroupsToFunctions(groups, options)}
210
- module.exports = {main}
211
210
  `
212
211
 
213
212
  // create a function for each group
214
213
  return code
215
214
  }
216
215
 
217
- const extension = 'obj'
216
+ const mimeType = 'model/obj'
218
217
 
219
- module.exports = {
220
- deserialize,
221
- extension
218
+ export {
219
+ mimeType,
220
+ deserialize
222
221
  }
@@ -1,12 +1,13 @@
1
- const fs = require('fs')
2
- const path = require('path')
3
- const test = require('ava')
1
+ import fs from 'fs'
2
+ import path from 'path'
4
3
 
5
- const samplesPath = path.dirname(require.resolve('@jscad/sample-files/package.json'))
4
+ import test from 'ava'
6
5
 
7
- const { geometries } = require('@jscad/modeling')
6
+ import { geom3 } from '@jscad/modeling'
8
7
 
9
- const deserializer = require('../index.js')
8
+ import { deserialize } from '../src/index.js'
9
+
10
+ const samplesPath = '../../../node_modules/@jscad/sample-files'
10
11
 
11
12
  const toArray = (polygons) => polygons.map((p) => p.vertices.map((v) => ([v[0], v[1], v[2]])))
12
13
 
@@ -14,9 +15,9 @@ test('deserialize simple obj to geometry', (t) => {
14
15
  const inputPath = path.resolve(samplesPath, 'obj/cube.obj')
15
16
  const inputFile = fs.readFileSync(inputPath, 'utf8')
16
17
 
17
- const observed = deserializer.deserialize({ output: 'geometry', addMetaData: false }, inputFile)
18
+ const observed = deserialize({ output: 'geometry', addMetaData: false }, inputFile)
18
19
  t.is(observed.length, 1)
19
- const polygons = geometries.geom3.toPolygons(observed[0])
20
+ const polygons = geom3.toPolygons(observed[0])
20
21
  t.deepEqual(polygons.length, 6)
21
22
 
22
23
  const observedVertices = toArray(polygons)
@@ -1,21 +1,22 @@
1
- const fs = require('fs')
2
- const path = require('path')
3
- const test = require('ava')
1
+ import fs from 'fs'
2
+ import path from 'path'
4
3
 
5
- const samplesPath = path.dirname(require.resolve('@jscad/sample-files/package.json'))
4
+ import test from 'ava'
6
5
 
7
- const deserializer = require('../index.js')
6
+ import { deserialize } from '../src/index.js'
7
+
8
+ const samplesPath = '../../../node_modules/@jscad/sample-files'
8
9
 
9
10
  test('translate simple obj file to jscad script', (t) => {
10
11
  const inputPath = path.resolve(samplesPath, 'obj/cube.obj')
11
12
  const inputFile = fs.readFileSync(inputPath, 'utf8')
12
13
 
13
- const observed = deserializer.deserialize({ output: 'script', addMetaData: false }, inputFile)
14
- const expected = `const {primitives} = require('@jscad/modeling')
14
+ const observed = deserialize({ output: 'script', addMetaData: false }, inputFile)
15
+ const expected = `import * from '@jscad/modeling'
15
16
 
16
17
  // groups: 1
17
18
  // points: 8
18
- const main = () => {
19
+ export const main = () => {
19
20
  // points are common to all geometries
20
21
  let points = [
21
22
  [-0.5,-0.5,0.5],
@@ -54,10 +55,9 @@ const group0 = (points) => {
54
55
  null,
55
56
  null,
56
57
  ]
57
- return primitives.polyhedron({ orientation: 'outward', points, faces, colors })
58
+ return polyhedron({ orientation: 'outward', points, faces, colors })
58
59
  }
59
60
 
60
- module.exports = {main}
61
61
  `
62
62
 
63
63
  t.deepEqual(observed, expected)
@@ -82,12 +82,12 @@ f 5 1 4 8
82
82
  f 5 6 2 1
83
83
  f 2 6 7 3
84
84
  `
85
- const observed = deserializer.deserialize({ filename: 'absolute', output: 'script', addMetaData: false }, data)
86
- const expected = `const {primitives} = require('@jscad/modeling')
85
+ const observed = deserialize({ filename: 'absolute', output: 'script', addMetaData: false }, data)
86
+ const expected = `import * from '@jscad/modeling'
87
87
 
88
88
  // groups: 1
89
89
  // points: 8
90
- const main = () => {
90
+ export const main = () => {
91
91
  // points are common to all geometries
92
92
  let points = [
93
93
  [0,2,2],
@@ -126,10 +126,9 @@ const group0 = (points) => {
126
126
  [0,0.5019607843137255,0.5019607843137255,1],
127
127
  [0,0.5019607843137255,0.5019607843137255,1],
128
128
  ]
129
- return primitives.polyhedron({ orientation: 'outward', points, faces, colors })
129
+ return polyhedron({ orientation: 'outward', points, faces, colors })
130
130
  }
131
131
 
132
- module.exports = {main}
133
132
  `
134
133
 
135
134
  t.deepEqual(observed, expected)
@@ -168,12 +167,12 @@ v 2.000000 0.000000 0.000000
168
167
  v 2.000000 0.000000 2.000000
169
168
  f -4 -3 -2 -1
170
169
  `
171
- const observed = deserializer.deserialize({ output: 'script', addMetaData: false }, data)
172
- const expected = `const {primitives} = require('@jscad/modeling')
170
+ const observed = deserialize({ output: 'script', addMetaData: false }, data)
171
+ const expected = `import * from '@jscad/modeling'
173
172
 
174
173
  // groups: 1
175
174
  // points: 24
176
- const main = () => {
175
+ export const main = () => {
177
176
  // points are common to all geometries
178
177
  let points = [
179
178
  [0,2,2],
@@ -228,10 +227,9 @@ const group0 = (points) => {
228
227
  null,
229
228
  null,
230
229
  ]
231
- return primitives.polyhedron({ orientation: 'outward', points, faces, colors })
230
+ return polyhedron({ orientation: 'outward', points, faces, colors })
232
231
  }
233
232
 
234
- module.exports = {main}
235
233
  `
236
234
  t.deepEqual(observed, expected)
237
235
  })