@jscad/x3d-serializer 2.4.5 → 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,214 +3,123 @@
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.4.5](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.4.4...@jscad/x3d-serializer@2.4.5) (2023-06-27)
7
-
6
+ # [3.0.0-alpha.0](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.4.2...@jscad/x3d-serializer@3.0.0-alpha.0) (2023-10-09)
8
7
 
9
8
  ### Bug Fixes
10
9
 
11
- * **x3d-serializer:** added specular highlights and conversion of shape names ([ba26567](https://github.com/jscad/OpenJSCAD.org/commit/ba26567f207a3e7529778ec89436956cf03592bf))
10
+ * **io:** fix io after V3 refactoring ([7a12bbd](https://github.com/jscad/OpenJSCAD.org/commit/7a12bbdb7b4b3df792a4c5b3c8b30a6a985a48f0))
12
11
 
12
+ ### Features
13
13
 
14
+ * **modeling:** reworked exports to expose a flattened API ([8235238](https://github.com/jscad/OpenJSCAD.org/commit/8235238ad63d063f1e501478cae1208deb130a9c))
14
15
 
16
+ ## [2.4.5](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.4.4...@jscad/x3d-serializer@2.4.5) (2023-06-27)
15
17
 
18
+ ### Bug Fixes
16
19
 
17
- ## [2.4.4](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.4.3...@jscad/x3d-serializer@2.4.4) (2023-04-30)
20
+ * **x3d-serializer:** added specular highlights and conversion of shape names ([ba26567](https://github.com/jscad/OpenJSCAD.org/commit/ba26567f207a3e7529778ec89436956cf03592bf))
18
21
 
22
+ ## [2.4.4](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.4.3...@jscad/x3d-serializer@2.4.4) (2023-04-30)
19
23
 
20
24
  ### Bug Fixes
21
25
 
22
26
  * **x3d-serializer:** corrected color and transparency conversions ([cc99548](https://github.com/jscad/OpenJSCAD.org/commit/cc9954853c30c6a82fcd26cda686e7f51f9fa304))
23
27
  * **x3d-serializer:** corrected colors, orientation of scene to Y up, and added new option for smoothing ([3444e2d](https://github.com/jscad/OpenJSCAD.org/commit/3444e2d462446694e62da71b130dfb4e56e92f82))
24
28
 
25
-
26
-
27
-
28
-
29
29
  ## [2.4.3](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.4.2...@jscad/x3d-serializer@2.4.3) (2022-11-26)
30
30
 
31
31
  **Note:** Version bump only for package @jscad/x3d-serializer
32
32
 
33
-
34
-
35
-
36
-
37
33
  ## [2.4.2](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.4.1...@jscad/x3d-serializer@2.4.2) (2022-08-21)
38
34
 
39
35
  **Note:** Version bump only for package @jscad/x3d-serializer
40
36
 
41
-
42
-
43
-
44
-
45
37
  ## [2.4.1](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.4.0...@jscad/x3d-serializer@2.4.1) (2022-07-17)
46
38
 
47
39
  **Note:** Version bump only for package @jscad/x3d-serializer
48
40
 
49
-
50
-
51
-
52
-
53
41
  # [2.4.0](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.3.9...@jscad/x3d-serializer@2.4.0) (2022-06-12)
54
42
 
55
-
56
43
  ### Features
57
44
 
58
45
  * **x3d-serializer:** enhanced to convert 2D geometry and path to X3D Polyline2D ([#1091](https://github.com/jscad/OpenJSCAD.org/issues/1091)) ([4f763a8](https://github.com/jscad/OpenJSCAD.org/commit/4f763a8def39f3b0454f2079f3c1fd7da52dd880))
59
46
 
60
-
61
-
62
-
63
-
64
47
  ## [2.3.9](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.3.8...@jscad/x3d-serializer@2.3.9) (2022-05-15)
65
48
 
66
49
  **Note:** Version bump only for package @jscad/x3d-serializer
67
50
 
68
-
69
-
70
-
71
-
72
51
  ## [2.3.8](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.3.7...@jscad/x3d-serializer@2.3.8) (2022-04-24)
73
52
 
74
53
  **Note:** Version bump only for package @jscad/x3d-serializer
75
54
 
76
-
77
-
78
-
79
-
80
55
  ## [2.3.7](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.3.6...@jscad/x3d-serializer@2.3.7) (2022-04-03)
81
56
 
82
57
  **Note:** Version bump only for package @jscad/x3d-serializer
83
58
 
84
-
85
-
86
-
87
-
88
59
  ## [2.3.6](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.3.5...@jscad/x3d-serializer@2.3.6) (2022-04-03)
89
60
 
90
61
  **Note:** Version bump only for package @jscad/x3d-serializer
91
62
 
92
-
93
-
94
-
95
-
96
63
  ## [2.3.5](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.3.4...@jscad/x3d-serializer@2.3.5) (2022-03-13)
97
64
 
98
65
  **Note:** Version bump only for package @jscad/x3d-serializer
99
66
 
100
-
101
-
102
-
103
-
104
67
  ## [2.3.4](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.3.3...@jscad/x3d-serializer@2.3.4) (2022-03-06)
105
68
 
106
69
  **Note:** Version bump only for package @jscad/x3d-serializer
107
70
 
108
-
109
-
110
-
111
-
112
71
  ## [2.3.3](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.3.2...@jscad/x3d-serializer@2.3.3) (2022-02-19)
113
72
 
114
73
  **Note:** Version bump only for package @jscad/x3d-serializer
115
74
 
116
-
117
-
118
-
119
-
120
75
  ## [2.3.2](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.3.1...@jscad/x3d-serializer@2.3.2) (2021-12-26)
121
76
 
122
77
  **Note:** Version bump only for package @jscad/x3d-serializer
123
78
 
124
-
125
-
126
-
127
-
128
79
  ## [2.3.1](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.3.0...@jscad/x3d-serializer@2.3.1) (2021-12-11)
129
80
 
130
81
  **Note:** Version bump only for package @jscad/x3d-serializer
131
82
 
132
-
133
-
134
-
135
-
136
83
  # [2.3.0](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.2.8...@jscad/x3d-serializer@2.3.0) (2021-11-07)
137
84
 
138
-
139
85
  ### Features
140
86
 
141
87
  * **io:** new serializer for OBJ ([#942](https://github.com/jscad/OpenJSCAD.org/issues/942)) ([baaae18](https://github.com/jscad/OpenJSCAD.org/commit/baaae18ad55252ec71b074bd85dea7d137a22eb8))
142
88
 
143
-
144
-
145
-
146
-
147
89
  ## [2.2.8](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.2.7...@jscad/x3d-serializer@2.2.8) (2021-10-17)
148
90
 
149
91
  **Note:** Version bump only for package @jscad/x3d-serializer
150
92
 
151
-
152
-
153
-
154
-
155
93
  ## [2.2.7](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.2.6...@jscad/x3d-serializer@2.2.7) (2021-10-04)
156
94
 
157
95
  **Note:** Version bump only for package @jscad/x3d-serializer
158
96
 
159
-
160
-
161
-
162
-
163
97
  ## [2.2.6](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.2.5...@jscad/x3d-serializer@2.2.6) (2021-09-27)
164
98
 
165
99
  **Note:** Version bump only for package @jscad/x3d-serializer
166
100
 
167
-
168
-
169
-
170
-
171
101
  ## [2.2.5](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.2.4...@jscad/x3d-serializer@2.2.5) (2021-09-09)
172
102
 
173
103
  **Note:** Version bump only for package @jscad/x3d-serializer
174
104
 
175
-
176
-
177
-
178
-
179
105
  ## [2.2.4](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.2.3...@jscad/x3d-serializer@2.2.4) (2021-06-20)
180
106
 
181
107
  **Note:** Version bump only for package @jscad/x3d-serializer
182
108
 
183
-
184
-
185
-
186
-
187
109
  ## [2.2.3](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.2.2...@jscad/x3d-serializer@2.2.3) (2021-06-11)
188
110
 
189
111
  **Note:** Version bump only for package @jscad/x3d-serializer
190
112
 
191
-
192
-
193
-
194
-
195
113
  ## [2.2.2](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.2.1...@jscad/x3d-serializer@2.2.2) (2021-06-01)
196
114
 
197
115
  **Note:** Version bump only for package @jscad/x3d-serializer
198
116
 
199
-
200
-
201
-
202
-
203
117
  ## [2.2.1](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.2.0...@jscad/x3d-serializer@2.2.1) (2021-04-20)
204
118
 
205
119
  **Note:** Version bump only for package @jscad/x3d-serializer
206
120
 
207
-
208
-
209
-
210
-
211
121
  # [2.2.0](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.0...@jscad/x3d-serializer@2.2.0) (2021-04-17)
212
122
 
213
-
214
123
  ### Bug Fixes
215
124
 
216
125
  * **all:** update dependencies ([d8c713a](https://github.com/jscad/OpenJSCAD.org/commit/d8c713a933b97a6d179ed3d3e923e188e334f99e))
@@ -218,18 +127,12 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
218
127
  * **io:** io revisited ([#714](https://github.com/jscad/OpenJSCAD.org/issues/714)) ([22f04f1](https://github.com/jscad/OpenJSCAD.org/commit/22f04f1b2894a82e24952655875e73b74727bf86))
219
128
  * **modeling:** V2 revisit modifiers ([#773](https://github.com/jscad/OpenJSCAD.org/issues/773)) ([1e28120](https://github.com/jscad/OpenJSCAD.org/commit/1e28120d2b8505dc1882cf3d607296d6fcd5526d))
220
129
 
221
-
222
130
  ### Features
223
131
 
224
132
  * **modeling:** V2 : rename option to align and center ([#775](https://github.com/jscad/OpenJSCAD.org/issues/775)) ([c5b0f48](https://github.com/jscad/OpenJSCAD.org/commit/c5b0f48bbd980b59876d73b673a0e3bef44d2b30))
225
133
 
226
-
227
-
228
-
229
-
230
134
  # [2.1.0](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.0...@jscad/x3d-serializer@2.1.0) (2021-04-15)
231
135
 
232
-
233
136
  ### Bug Fixes
234
137
 
235
138
  * **all:** update dependencies ([d8c713a](https://github.com/jscad/OpenJSCAD.org/commit/d8c713a933b97a6d179ed3d3e923e188e334f99e))
@@ -237,210 +140,118 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
237
140
  * **io:** io revisited ([#714](https://github.com/jscad/OpenJSCAD.org/issues/714)) ([22f04f1](https://github.com/jscad/OpenJSCAD.org/commit/22f04f1b2894a82e24952655875e73b74727bf86))
238
141
  * **modeling:** V2 revisit modifiers ([#773](https://github.com/jscad/OpenJSCAD.org/issues/773)) ([1e28120](https://github.com/jscad/OpenJSCAD.org/commit/1e28120d2b8505dc1882cf3d607296d6fcd5526d))
239
142
 
240
-
241
143
  ### Features
242
144
 
243
145
  * **modeling:** V2 : rename option to align and center ([#775](https://github.com/jscad/OpenJSCAD.org/issues/775)) ([c5b0f48](https://github.com/jscad/OpenJSCAD.org/commit/c5b0f48bbd980b59876d73b673a0e3bef44d2b30))
244
146
 
245
-
246
-
247
-
248
-
249
147
  # [2.0.0](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.12...@jscad/x3d-serializer@2.0.0) (2021-04-12)
250
148
 
251
149
  **Note:** Version bump only for package @jscad/x3d-serializer
252
150
 
253
-
254
-
255
-
256
-
257
151
  # [2.0.0-alpha.12](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.11...@jscad/x3d-serializer@2.0.0-alpha.12) (2021-03-07)
258
152
 
259
-
260
153
  ### Bug Fixes
261
154
 
262
155
  * **modeling:** V2 revisit modifiers ([#773](https://github.com/jscad/OpenJSCAD.org/issues/773)) ([1e28120](https://github.com/jscad/OpenJSCAD.org/commit/1e28120d2b8505dc1882cf3d607296d6fcd5526d))
263
156
 
264
-
265
157
  ### Features
266
158
 
267
159
  * **modeling:** V2 : rename option to align and center ([#775](https://github.com/jscad/OpenJSCAD.org/issues/775)) ([c5b0f48](https://github.com/jscad/OpenJSCAD.org/commit/c5b0f48bbd980b59876d73b673a0e3bef44d2b30))
268
160
 
269
-
270
-
271
-
272
-
273
161
  # [2.0.0-alpha.11](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.10...@jscad/x3d-serializer@2.0.0-alpha.11) (2021-02-07)
274
162
 
275
163
  **Note:** Version bump only for package @jscad/x3d-serializer
276
164
 
277
-
278
-
279
-
280
-
281
165
  # [2.0.0-alpha.10](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.9...@jscad/x3d-serializer@2.0.0-alpha.10) (2021-01-02)
282
166
 
283
167
  **Note:** Version bump only for package @jscad/x3d-serializer
284
168
 
285
-
286
-
287
-
288
-
289
169
  # [2.0.0-alpha.9](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.8...@jscad/x3d-serializer@2.0.0-alpha.9) (2020-12-04)
290
170
 
291
171
  **Note:** Version bump only for package @jscad/x3d-serializer
292
172
 
293
-
294
-
295
-
296
-
297
173
  # [2.0.0-alpha.8](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.7...@jscad/x3d-serializer@2.0.0-alpha.8) (2020-11-07)
298
174
 
299
-
300
175
  ### Bug Fixes
301
176
 
302
177
  * **io:** io revisited ([#714](https://github.com/jscad/OpenJSCAD.org/issues/714)) ([22f04f1](https://github.com/jscad/OpenJSCAD.org/commit/22f04f1b2894a82e24952655875e73b74727bf86))
303
178
 
304
-
305
-
306
-
307
-
308
179
  # [2.0.0-alpha.7](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.6...@jscad/x3d-serializer@2.0.0-alpha.7) (2020-10-11)
309
180
 
310
-
311
181
  ### Bug Fixes
312
182
 
313
183
  * **all:** V2 : several fixes for modeling ([#705](https://github.com/jscad/OpenJSCAD.org/issues/705)) ([62017a4](https://github.com/jscad/OpenJSCAD.org/commit/62017a41214169d6e000f1e0c11aaefdd68e1097))
314
184
 
315
-
316
-
317
-
318
-
319
185
  # [2.0.0-alpha.6](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.5...@jscad/x3d-serializer@2.0.0-alpha.6) (2020-09-29)
320
186
 
321
187
  **Note:** Version bump only for package @jscad/x3d-serializer
322
188
 
323
-
324
-
325
-
326
-
327
189
  # [2.0.0-alpha.5](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.4...@jscad/x3d-serializer@2.0.0-alpha.5) (2020-09-28)
328
190
 
329
191
  **Note:** Version bump only for package @jscad/x3d-serializer
330
192
 
331
-
332
-
333
-
334
-
335
193
  # [2.0.0-alpha.4](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.3...@jscad/x3d-serializer@2.0.0-alpha.4) (2020-09-19)
336
194
 
337
195
  **Note:** Version bump only for package @jscad/x3d-serializer
338
196
 
339
-
340
-
341
-
342
-
343
197
  # [2.0.0-alpha.3](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.2...@jscad/x3d-serializer@2.0.0-alpha.3) (2020-09-08)
344
198
 
345
199
  **Note:** Version bump only for package @jscad/x3d-serializer
346
200
 
347
-
348
-
349
-
350
-
351
201
  # [2.0.0-alpha.2](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.1...@jscad/x3d-serializer@2.0.0-alpha.2) (2020-09-02)
352
202
 
353
-
354
203
  ### Bug Fixes
355
204
 
356
205
  * **all:** update dependencies ([d8c713a](https://github.com/jscad/OpenJSCAD.org/commit/d8c713a933b97a6d179ed3d3e923e188e334f99e))
357
206
 
358
-
359
-
360
-
361
-
362
207
  # [2.0.0-alpha.1](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.0.0-alpha.0...@jscad/x3d-serializer@2.0.0-alpha.1) (2020-08-19)
363
208
 
364
209
  **Note:** Version bump only for package @jscad/x3d-serializer
365
210
 
366
-
367
-
368
-
369
-
370
211
  # 2.0.0-alpha.0 (2020-08-13)
371
212
 
372
-
373
213
  ### Features
374
214
 
375
215
  * **x3d-serializer:** overhaul for V2 (#476)
376
216
 
377
-
378
-
379
-
380
-
381
217
  <a name="0.2.0"></a>
382
218
  # [0.2.0](https://github.com/jscad/io/compare/@jscad/x3d-serializer@0.1.2...@jscad/x3d-serializer@0.2.0) (2018-11-25)
383
219
 
384
-
385
-
386
220
  <a name="0.1.2"></a>
387
221
  ## [0.1.2](https://github.com/jscad/io/compare/@jscad/x3d-serializer@0.1.1...@jscad/x3d-serializer@0.1.2) (2018-09-02)
388
222
 
389
-
390
223
  ### Bug Fixes
391
224
 
392
225
  * **svg deserializer:** fixed svg-deserializer to work with Inkscape files ([#72](https://github.com/jscad/io/issues/72)) ([f35ea5e](https://github.com/jscad/io/commit/f35ea5e))
393
226
 
394
-
395
-
396
-
397
227
  <a name="0.1.1"></a>
398
228
  ## [0.1.1](https://github.com/jscad/io/compare/@jscad/x3d-serializer@0.1.0...@jscad/x3d-serializer@0.1.1) (2017-12-14)
399
229
 
400
-
401
-
402
-
403
230
  **Note:** Version bump only for package @jscad/x3d-serializer
404
231
 
405
232
  <a name="0.1.0"></a>
406
233
  # [0.1.0](https://github.com/jscad/io/compare/@jscad/x3d-serializer@0.0.6...@jscad/x3d-serializer@0.1.0) (2017-11-29)
407
234
 
408
-
409
235
  ### Features
410
236
 
411
237
  * 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))
412
238
 
413
-
414
-
415
-
416
239
  <a name="0.0.6"></a>
417
240
  ## [0.0.6](https://github.com/jscad/io/compare/@jscad/x3d-serializer@0.0.5...@jscad/x3d-serializer@0.0.6) (2017-11-04)
418
241
 
419
-
420
-
421
-
422
242
  **Note:** Version bump only for package @jscad/x3d-serializer
423
243
 
424
244
  <a name="0.0.5"></a>
425
245
  ## [0.0.5](https://github.com/jscad/io/compare/@jscad/x3d-serializer@0.0.4...@jscad/x3d-serializer@0.0.5) (2017-10-30)
426
246
 
427
-
428
-
429
-
430
247
  **Note:** Version bump only for package @jscad/x3d-serializer
431
248
 
432
249
  <a name="0.0.4"></a>
433
250
  ## [0.0.4](https://github.com/jscad/io/compare/@jscad/x3d-serializer@0.0.3...@jscad/x3d-serializer@0.0.4) (2017-10-10)
434
251
 
435
-
436
-
437
-
438
252
  **Note:** Version bump only for package @jscad/x3d-serializer
439
253
 
440
254
  <a name="0.0.3"></a>
441
255
  ## 0.0.3 (2017-10-10)
442
256
 
443
-
444
-
445
-
446
257
  **Note:** Version bump only for package @jscad/x3d-serializer
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)
@@ -76,5 +76,7 @@ Small Note: If editing this README, please conform to the [standard-readme](http
76
76
 
77
77
  ## License
78
78
 
79
+ Copyright (c) JSCAD Organization
80
+
79
81
  [The MIT License (MIT)](../../LICENSE)
80
82
  (unless specified otherwise)
@@ -0,0 +1,13 @@
1
+ /**
2
+ * X3D Serializer for JSCAD
3
+ * @module @jscad/x3d-serializer
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 flatten$1=arr=>arr.reduce(((acc,val)=>Array.isArray(val)?acc.concat(flatten$1(val)):acc.concat(val)),[]),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},divide$1=(out,a,b)=>(out[0]=a[0]/b[0],out[1]=a[1]/b[1],out[2]=a[2]/b[2],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),snap$2=(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$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:divide$1,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:snap$2,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,toPoints$3=geometry=>{const points=[];return toOutlines(geometry).forEach((outline=>{outline.forEach((point=>{points.push(point)}))})),points},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])]};var index$a=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:toPoints$3,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}`)}))}};var index$7=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);var index$6=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);var index$5=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};var index$3=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 cache$2=new WeakMap,expand2=(bbox,point)=>{0===bbox.length?(bbox[0]=fromVec2([0,0,0],point),bbox[1]=fromVec2([0,0,0],point)):(min$1(bbox[0],bbox[0],point),max$1(bbox[1],bbox[1],point))},expand3=(bbox,vertex)=>{0===bbox.length?(bbox[0]=clone$9(vertex),bbox[1]=clone$9(vertex)):(min$2(bbox[0],bbox[0],vertex),max$2(bbox[1],bbox[1],vertex))},measureCached$1=(geometry,measureFn)=>{let boundingBox=cache$2.get(geometry);return boundingBox||(boundingBox=measureFn(geometry),0===boundingBox.length&&(boundingBox[0]=[0,0,0],boundingBox[1]=[0,0,0]),cache$2.set(geometry,boundingBox),boundingBox)},measureBoundingBoxOfPath2=geometry=>{const boundingBox=[];return toPoints$1(geometry).forEach((point=>{expand2(boundingBox,point)})),boundingBox},measureBoundingBoxOfGeom2=geometry=>{const boundingBox=[];return toPoints$3(geometry).forEach((point=>{expand2(boundingBox,point)})),boundingBox},measureBoundingBoxOfGeom3=geometry=>{const boundingBox=[];return toPolygons$1(geometry).forEach((polygon=>{toVertices$1(polygon).forEach((vertex=>{expand3(boundingBox,vertex)}))})),boundingBox},measureBoundingBoxOfSlice=geometry=>{const boundingBox=[];return geometry.contours.forEach((contour=>{contour.forEach((vertex=>{expand3(boundingBox,vertex)}))})),boundingBox},measureBoundingBox=(...geometries)=>{if(0===(geometries=flatten$1(geometries)).length)throw new Error("wrong number of arguments");const results=geometries.map((geometry=>isA$2(geometry)?measureCached$1(geometry,measureBoundingBoxOfPath2):isA$5(geometry)?measureCached$1(geometry,measureBoundingBoxOfGeom2):isA$3(geometry)?measureCached$1(geometry,measureBoundingBoxOfGeom3):isA(geometry)?measureCached$1(geometry,measureBoundingBoxOfSlice):[[0,0,0],[0,0,0]]));return 1===results.length?results[0]:results},calculateEpsilonFromBounds=(bounds,dimensions)=>{let total=0;for(let i=0;i<dimensions;i++)total+=bounds[1][i]-bounds[0][i];return EPS*total/dimensions},createEdges=polygon=>{const vertices=toVertices$1(polygon),edges=[];for(let i=0;i<vertices.length;i++){const j=(i+1)%vertices.length,edge={v1:vertices[i],v2:vertices[j]};edges.push(edge)}for(let i=0;i<edges.length;i++){const j=(i+1)%vertices.length;edges[i].next=edges[j],edges[j].prev=edges[i]}return edges},insertEdge=(edges,edge)=>{const key=`${edge.v1}:${edge.v2}`;edges.set(key,edge)},deleteEdge=(edges,edge)=>{const key=`${edge.v1}:${edge.v2}`;edges.delete(key)},findOppositeEdge=(edges,edge)=>{const key=`${edge.v2}:${edge.v1}`;return edges.get(key)},calculateAnglesBetween=(current,opposite,normal)=>{let v0=current.prev.v1,v1=current.prev.v2,v2=opposite.next.v2;const angle1=calculateAngle(v0,v1,v2,normal);return v0=opposite.prev.v1,v1=opposite.prev.v2,v2=current.next.v2,[angle1,calculateAngle(v0,v1,v2,normal)]},v1=[0,0,0],v2=[0,0,0],calculateAngle=(prevVertex,midVertex,nextVertex,normal)=>{const d0=subtract$3(v1,midVertex,prevVertex),d1=subtract$3(v2,nextVertex,midVertex);return cross$1(d0,d0,d1),dot$2(d0,normal)},mergePolygons=(epsilon,polygons)=>{const polygonsPerPlane=[];polygons.forEach((polygon=>{const mapping=polygonsPerPlane.find((element=>{return plane1=element[0],plane2=plane(polygon),Math.abs(plane1[3]-plane2[3])<15e-8&&(a=plane1,b=plane2,Math.abs(a[0]-b[0])<=1e-13&&Math.abs(a[1]-b[1])<=1e-13&&Math.abs(a[2]-b[2])<=1e-13);var a,b,plane1,plane2}));mapping?mapping[1].push(polygon):polygonsPerPlane.push([plane(polygon),[polygon]])}));let destPolygons=[];return polygonsPerPlane.forEach((mapping=>{const retesselatedPolygons=(sourcePolygons=>{if(sourcePolygons.length<2)return sourcePolygons;const normal=sourcePolygons[0].plane,polygons=sourcePolygons.slice(),edgeList=new Map;for(;polygons.length>0;){const polygon=polygons.shift(),edges=createEdges(polygon);for(let i=0;i<edges.length;i++){const current=edges[i],opposite=findOppositeEdge(edgeList,current);if(opposite){const angles=calculateAnglesBetween(current,opposite,normal);if(angles[0]>=0&&angles[1]>=0){const edge1=opposite.next,edge2=current.next;current.prev.next=opposite.next,current.next.prev=opposite.prev,opposite.prev.next=current.next,opposite.next.prev=current.prev,current.v1=null,current.v2=null,current.next=null,current.prev=null,deleteEdge(edgeList,opposite),opposite.v1=null,opposite.v2=null,opposite.next=null,opposite.prev=null;const mergeEdges=(list,e1,e2)=>{const newEdge={v1:e2.v1,v2:e1.v2,next:e1.next,prev:e2.prev};e2.prev.next=newEdge,e1.next.prev=newEdge,deleteEdge(list,e1),e1.v1=null,e1.v2=null,e1.next=null,e1.prev=null,deleteEdge(list,e2),e2.v1=null,e2.v2=null,e2.next=null,e2.prev=null};0===angles[0]&&mergeEdges(edgeList,edge1,edge1.prev),0===angles[1]&&mergeEdges(edgeList,edge2,edge2.prev)}}else current.next&&insertEdge(edgeList,current)}}const destPolygons=[];return edgeList.forEach((edge=>{const polygon=(edge=>{let polygon;const vertices=[];for(;edge.next;){const next=edge.next;vertices.push(edge.v1),edge.v1=null,edge.v2=null,edge.next=null,edge.prev=null,edge=next}return vertices.length>0&&(polygon=create$7(vertices)),polygon})(edge);polygon&&destPolygons.push(polygon)})),edgeList.clear(),destPolygons})(mapping[1]);destPolygons=destPolygons.concat(retesselatedPolygons)})),destPolygons},getTag=vertex=>`${vertex}`,addSide=(sideMap,vertextag2sidestart,vertextag2sideend,vertex0,vertex1,polygonIndex)=>{const startTag=getTag(vertex0),endTag=getTag(vertex1),newSideTag=`${startTag}/${endTag}`,reverseSideTag=`${endTag}/${startTag}`;if(sideMap.has(reverseSideTag))return deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,vertex1,vertex0,null),null;const newSideObj={vertex0:vertex0,vertex1:vertex1,polygonIndex:polygonIndex};return sideMap.has(newSideTag)?sideMap.get(newSideTag).push(newSideObj):sideMap.set(newSideTag,[newSideObj]),vertextag2sidestart.has(startTag)?vertextag2sidestart.get(startTag).push(newSideTag):vertextag2sidestart.set(startTag,[newSideTag]),vertextag2sideend.has(endTag)?vertextag2sideend.get(endTag).push(newSideTag):vertextag2sideend.set(endTag,[newSideTag]),newSideTag},deleteSide=(sidemap,vertextag2sidestart,vertextag2sideend,vertex0,vertex1,polygonIndex)=>{const startTag=getTag(vertex0),endTag=getTag(vertex1),sideTag=`${startTag}/${endTag}`;let idx=-1;const sideObjs=sidemap.get(sideTag);for(let i=0;i<sideObjs.length;i++){const sideObj=sideObjs[i];let sideTag=getTag(sideObj.vertex0);if(sideTag===startTag&&(sideTag=getTag(sideObj.vertex1),sideTag===endTag&&(null===polygonIndex||sideObj.polygonIndex===polygonIndex))){idx=i;break}}sideObjs.splice(idx,1),0===sideObjs.length&&sidemap.delete(sideTag),idx=vertextag2sidestart.get(startTag).indexOf(sideTag),vertextag2sidestart.get(startTag).splice(idx,1),0===vertextag2sidestart.get(startTag).length&&vertextag2sidestart.delete(startTag),idx=vertextag2sideend.get(endTag).indexOf(sideTag),vertextag2sideend.get(endTag).splice(idx,1),0===vertextag2sideend.get(endTag).length&&vertextag2sideend.delete(endTag)},generalizeGeom3=(options,geometry)=>{const{snap:snap,simplify:simplify,triangulate:triangulate}=Object.assign({},{snap:!1,simplify:!1,triangulate:!1},options),epsilon=((...geometries)=>{if(0===(geometries=flatten$1(geometries)).length)throw new Error("wrong number of arguments");const results=geometries.map((geometry=>isA$2(geometry)||isA$5(geometry)?calculateEpsilonFromBounds(measureBoundingBox(geometry),2):isA$3(geometry)||isA(geometry)?calculateEpsilonFromBounds(measureBoundingBox(geometry),3):0));return 1===results.length?results[0]:results})(geometry);let polygons=toPolygons$1(geometry);snap&&(polygons=((epsilon,polygons)=>{let newPolygons=polygons.map((polygon=>{const snapVertices=polygon.vertices.map((vertex=>snap$2([0,0,0],vertex,epsilon))),newVertices=[];for(let i=0;i<snapVertices.length;i++){const j=(i+1)%snapVertices.length;equals$7(snapVertices[i],snapVertices[j])||newVertices.push(snapVertices[i])}const newPolygon=create$7(newVertices);return polygon.color&&(newPolygon.color=polygon.color),newPolygon}));const epsilonArea=epsilon*epsilon*Math.sqrt(3)/4;return newPolygons=newPolygons.filter((polygon=>((epsilon,polygon)=>{const area=Math.abs(measureArea$2(polygon));return Number.isFinite(area)&&area>epsilon})(epsilonArea,polygon))),newPolygons})(epsilon,polygons)),simplify&&(polygons=mergePolygons(0,polygons)),triangulate&&(polygons=(polygons=>{const sideMap=new Map;for(let polygonIndex=0;polygonIndex<polygons.length;polygonIndex++){const polygon=polygons[polygonIndex],numVertices=polygon.vertices.length;if(numVertices>=3){let vertex=polygon.vertices[0],vertexTag=getTag(vertex);for(let vertexIndex=0;vertexIndex<numVertices;vertexIndex++){let nextVertexIndex=vertexIndex+1;nextVertexIndex===numVertices&&(nextVertexIndex=0);const nextVertex=polygon.vertices[nextVertexIndex],nextVertexTag=getTag(nextVertex),sideTag=`${vertexTag}/${nextVertexTag}`,reverseSideTag=`${nextVertexTag}/${vertexTag}`;if(sideMap.has(reverseSideTag)){const ar=sideMap.get(reverseSideTag);ar.splice(-1,1),0===ar.length&&sideMap.delete(reverseSideTag)}else{const sideobj={vertex0:vertex,vertex1:nextVertex,polygonIndex:polygonIndex};sideMap.has(sideTag)?sideMap.get(sideTag).push(sideobj):sideMap.set(sideTag,[sideobj])}vertex=nextVertex,vertexTag=nextVertexTag}}else console.warn("warning: invalid polygon found during insertTjunctions")}if(sideMap.size>0){const vertextag2sidestart=new Map,vertextag2sideend=new Map,sidesToCheck=new Map;for(const[sidetag,sideObjs]of sideMap)sidesToCheck.set(sidetag,!0),sideObjs.forEach((sideObj=>{const starttag=getTag(sideObj.vertex0),endtag=getTag(sideObj.vertex1);vertextag2sidestart.has(starttag)?vertextag2sidestart.get(starttag).push(sidetag):vertextag2sidestart.set(starttag,[sidetag]),vertextag2sideend.has(endtag)?vertextag2sideend.get(endtag).push(sidetag):vertextag2sideend.set(endtag,[sidetag])}));const newPolygons=polygons.slice(0);for(;0!==sideMap.size;){for(const sideTag of sideMap.keys())sidesToCheck.set(sideTag,!0);let doneSomething=!1;for(;;){const sideTags=Array.from(sidesToCheck.keys());if(0===sideTags.length)break;const sideTagToCheck=sideTags[0];let doneWithSide=!0;if(sideMap.has(sideTagToCheck)){const sideObj=sideMap.get(sideTagToCheck)[0];for(let directionIndex=0;directionIndex<2;directionIndex++){const startVertex=0===directionIndex?sideObj.vertex0:sideObj.vertex1,endVertex=0===directionIndex?sideObj.vertex1:sideObj.vertex0,startVertexTag=getTag(startVertex),endVertexTag=getTag(endVertex);let matchingSides=[];0===directionIndex?vertextag2sideend.has(startVertexTag)&&(matchingSides=vertextag2sideend.get(startVertexTag)):vertextag2sidestart.has(startVertexTag)&&(matchingSides=vertextag2sidestart.get(startVertexTag));for(let matchingSideIndex=0;matchingSideIndex<matchingSides.length;matchingSideIndex++){const matchingSideTag=matchingSides[matchingSideIndex],matchingSide=sideMap.get(matchingSideTag)[0],matchingSideStartVertex=0===directionIndex?matchingSide.vertex0:matchingSide.vertex1;if(0===directionIndex?matchingSide.vertex1:matchingSide.vertex0,getTag(matchingSideStartVertex)===endVertexTag){deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,startVertex,endVertex,null),deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,endVertex,startVertex,null),doneWithSide=!1,directionIndex=2,doneSomething=!0;break}{const startPos=startVertex,endPos=endVertex,direction=subtract$3([0,0,0],matchingSideStartVertex,startPos),t=dot$2(subtract$3([0,0,0],endPos,startPos),direction)/dot$2(direction,direction);if(t>0&&t<1){const closestVertex=scale$3([0,0,0],direction,t);if(add$1(closestVertex,closestVertex,startPos),squaredDistance$1(closestVertex,endPos)<EPS*EPS){const polygonIndex=matchingSide.polygonIndex,polygon=newPolygons[polygonIndex],insertionVertexTag=getTag(matchingSide.vertex1);let insertionVertexTagIndex=-1;for(let i=0;i<polygon.vertices.length;i++)if(getTag(polygon.vertices[i])===insertionVertexTag){insertionVertexTagIndex=i;break}const newVertices=polygon.vertices.slice(0);newVertices.splice(insertionVertexTagIndex,0,endVertex);const newPolygon=create$7(newVertices);newPolygons[polygonIndex]=newPolygon,deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,matchingSide.vertex0,matchingSide.vertex1,polygonIndex);const newSideTag1=addSide(sideMap,vertextag2sidestart,vertextag2sideend,matchingSide.vertex0,endVertex,polygonIndex),newSideTag2=addSide(sideMap,vertextag2sidestart,vertextag2sideend,endVertex,matchingSide.vertex1,polygonIndex);null!==newSideTag1&&sidesToCheck.set(newSideTag1,!0),null!==newSideTag2&&sidesToCheck.set(newSideTag2,!0),doneWithSide=!1,directionIndex=2,doneSomething=!0;break}}}}}}doneWithSide&&sidesToCheck.delete(sideTagToCheck)}if(!doneSomething)break}polygons=newPolygons}return sideMap.clear(),polygons})(polygons),polygons=((epsilon,polygons)=>{const triangles=[];return polygons.forEach((polygon=>{((epsilon,polygon,triangles)=>{const nv=polygon.vertices.length;if(nv>3){if(nv>4){const midpoint=[0,0,0];polygon.vertices.forEach((vertex=>add$1(midpoint,midpoint,vertex))),snap$2(midpoint,divide$1(midpoint,midpoint,[nv,nv,nv]),epsilon);for(let i=0;i<nv;i++){const poly=create$7([midpoint,polygon.vertices[i],polygon.vertices[(i+1)%nv]]);polygon.color&&(poly.color=polygon.color),triangles.push(poly)}return}const poly0=create$7([polygon.vertices[0],polygon.vertices[1],polygon.vertices[2]]),poly1=create$7([polygon.vertices[0],polygon.vertices[2],polygon.vertices[3]]);return polygon.color&&(poly0.color=polygon.color,poly1.color=polygon.color),void triangles.push(poly0,poly1)}triangles.push(polygon)})(epsilon,polygon,triangles)})),triangles})(epsilon,polygons));const clone=Object.assign({},geometry);return clone.polygons=polygons,clone},flatten=arr=>arr.reduce(((acc,val)=>Array.isArray(val)?acc.concat(flatten(val)):acc.concat(val)),[]),stringify=(a,indentation)=>{const cr=indentation>0?"\n":"",indent=(indentation=>{if(!(indentation>0))return txt=>txt;const space=" ".repeat(indentation);return txt=>{if("string"!=typeof txt)return txt;const arr=txt.split("\n");return 1===arr.length?space+txt:arr.map((e=>""===e.trim()?e:space+e)).join("\n")}})(indentation),rec=a=>{let res,body="",isFlat=!0;return a.some(((e,i,arr)=>{if(0===i)return res="<"+e,1===arr.length;if(1===i){if((o=e)&&"[object Object]"===Object.prototype.toString.call(o))return Object.keys(e).forEach((key=>{let val=e[key];Array.isArray(val)&&(val=val.join(" ")),res+=" "+key+'="'+val+'"'})),2===arr.length||(res+=">",!1);res+=">"}var o;switch(typeof e){case"string":case"number":case"boolean":case"undefined":return body+=e+cr,!1}return isFlat=!1,body+=rec(e),!1}))?res+"/>"+cr:isFlat?res+body.split("\n").filter((e=>""!==e.trim())).join("\n")+"</"+a[0]+">"+cr:res+cr+indent(body)+"</"+a[0]+">"+cr};return rec(a)},mimeType="model/x3d+xml",defNames=new Map,serialize=(options,...objects)=>{if(options=Object.assign({},{color:[0,0,1,1],shininess:8/256,smooth:!1,decimals:1e3,metadata:!0,unit:"millimeter",statusCallback:null},options),0===(objects=(objects=flatten(objects)).filter((object=>index$6.isA(object)||index$a.isA(object)||index$5.isA(object)))).length)throw new Error("expected one or more geom3/geom2/path2 objects");options.statusCallback&&options.statusCallback({progress:0});let body=["X3D",{profile:"Interchange",version:"3.3","xmlns:xsd":"http://www.w3.org/2001/XMLSchema-instance","xsd:noNamespaceSchemaLocation":"http://www.web3d.org/specifications/x3d-3.3.xsd"}];options.metadata?body.push(["head",{},["meta",{name:"creator",content:"Created by JSCAD"}],["meta",{name:"reference",content:"https://www.openjscad.xyz"}],["meta",{name:"created",content:(new Date).toISOString()}]]):body.push(["head",{},["meta",{name:"creator",content:"Created by JSCAD"}]]),body=body.concat(convertObjects(objects,options));const contents=`<?xml version="1.0" encoding="UTF-8"?>\n${stringify(body,2)}`;return options&&options.statusCallback&&options.statusCallback({progress:100}),[contents]},convertObjects=(objects,options)=>{const shapes=[];objects.forEach(((object,i)=>{if(options.statusCallback&&options.statusCallback({progress:100*i/objects.length}),index$6.isA(object)){object=((options,...geometries)=>{if(0===(geometries=flatten$1(geometries)).length)throw new Error("wrong number of arguments");const results=geometries.map((geometry=>{if(isA$2(geometry))return((options,geometry)=>geometry)(0,geometry);if(isA$5(geometry))return((options,geometry)=>geometry)(0,geometry);if(isA$3(geometry))return generalizeGeom3(options,geometry);throw new Error("invalid geometry")}));return 1===results.length?results[0]:results})({snap:!0,triangulate:!0},object);index$6.toPolygons(object).length>0&&shapes.push(convertGeom3(object,options))}index$a.isA(object)&&shapes.push(convertGeom2(object,options)),index$5.isA(object)&&shapes.push(convertPath2(object,options))}));return[["Scene",{},["Transform",{rotation:"1 0 0 -1.5708"},...shapes]]]},convertPath2=(object,options)=>{const points=index$5.toPoints(object).slice();points.length>1&&object.isClosed&&points.push(points[0]);const shape=["Shape",shapeAttributes(object),convertPolyline2D(index$3.create(points))];return object.color&&shape.push(convertAppearance(object,"emissiveColor",options)),shape},convertGeom2=(object,options)=>{const outlines=index$a.toOutlines(object),group=["Group",{}];return outlines.forEach((outline=>{outline.length>1&&outline.push(outline[0]);const shape=["Shape",shapeAttributes(object),convertPolyline2D(index$3.create(outline))];object.color&&shape.push(convertAppearance(object,"emissiveColor",options)),group.push(shape)})),group},shapeAttributes=(object,attributes={})=>(object.id&&Object.assign(attributes,{DEF:checkDefName(object.id)}),attributes),checkDefName=defName=>{const count=defNames.get(defName)||0;return defNames.set(defName,count+1),count>0&&console.warn(`Warning: object.id set as DEF but not unique. ${defName} set ${count+1} times.`),defName},convertPolyline2D=(object,options)=>["Polyline2D",{lineSegments:object.points.map((p=>`${p[0]} ${p[1]}`)).join(" ")}],convertAppearance=(object,colorField,options)=>{const materialFields={[colorField]:object.color.slice(0,3).join(" "),transparency:roundToDecimals(1-object.color[3],options)};return"diffuseColor"===colorField&&Object.assign(materialFields,{specularColor:"0.2 0.2 0.2",shininess:options.shininess}),["Appearance",["Material",materialFields]]},convertGeom3=(object,options)=>{const shape=["Shape",shapeAttributes(object),convertMesh(object,options)];let appearance=["Appearance",{},["Material"]];return object.color&&(appearance=convertAppearance(object,"diffuseColor",options)),shape.push(appearance),shape},convertMesh=(object,options)=>{const mesh=convertToTriangles(object,options),lists=polygons2coordinates(mesh,options),indexList=lists[0].join(" "),pointList=lists[1].join(" "),colorList=lists[2].join(" "),faceset=["IndexedTriangleSet",{ccw:"true",colorPerVertex:"false",normalPerVertex:options.smooth,solid:"false",index:indexList},["Coordinate",{point:pointList}]];return object.color||faceset.push(["Color",{color:colorList}]),faceset},convertToTriangles=(object,options)=>{const triangles=[];return index$6.toPolygons(object).forEach((poly=>{const firstVertex=poly.vertices[0];for(let i=poly.vertices.length-3;i>=0;i--){const triangle=index$7.create([firstVertex,poly.vertices[i+1],poly.vertices[i+2]]);let color=options.color;object.color&&(color=object.color),poly.color&&(color=poly.color),triangle.color=color,triangles.push(triangle)}})),triangles},roundToDecimals=(float,options)=>Math.round(float*options.decimals)/options.decimals,polygons2coordinates=(polygons,options)=>{const indexList=[],pointList=[],colorList=[],vertexTagToCoordIndexMap=new Map;return polygons.forEach((polygon=>{const polygonVertexIndices=[],numvertices=polygon.vertices.length;for(let i=0;i<numvertices;i++){const vertex=polygon.vertices[i],id=`${vertex[0]},${vertex[1]},${vertex[2]}`;if(!vertexTagToCoordIndexMap.has(id)){const x=roundToDecimals(vertex[0],options),y=roundToDecimals(vertex[1],options),z=roundToDecimals(vertex[2],options);pointList.push(`${x} ${y} ${z}`),vertexTagToCoordIndexMap.set(id,pointList.length-1)}polygonVertexIndices.push(vertexTagToCoordIndexMap.get(id))}indexList.push(polygonVertexIndices.join(" ")),colorList.push(((polygon,options)=>{let color=options.color;return polygon.color&&(color=polygon.color),`${color[0]} ${color[1]} ${color[2]}`})(polygon,options))})),vertexTagToCoordIndexMap.clear(),[indexList,pointList,colorList]};export{mimeType,serialize};
@@ -0,0 +1,14 @@
1
+ /**
2
+ * X3D Serializer for JSCAD
3
+ * @module @jscad/x3d-serializer
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 flatten$1=arr=>arr.reduce(((acc,val)=>Array.isArray(val)?acc.concat(flatten$1(val)):acc.concat(val)),[]),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},divide$1=(out,a,b)=>(out[0]=a[0]/b[0],out[1]=a[1]/b[1],out[2]=a[2]/b[2],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),snap$2=(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$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:divide$1,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:snap$2,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,toPoints$3=geometry=>{const points=[];return toOutlines(geometry).forEach((outline=>{outline.forEach((point=>{points.push(point)}))})),points},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])]};var index$a=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:toPoints$3,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}`)}))}};var index$7=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);var index$6=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);var index$5=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};var index$3=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 cache$2=new WeakMap,expand2=(bbox,point)=>{0===bbox.length?(bbox[0]=fromVec2([0,0,0],point),bbox[1]=fromVec2([0,0,0],point)):(min$1(bbox[0],bbox[0],point),max$1(bbox[1],bbox[1],point))},expand3=(bbox,vertex)=>{0===bbox.length?(bbox[0]=clone$9(vertex),bbox[1]=clone$9(vertex)):(min$2(bbox[0],bbox[0],vertex),max$2(bbox[1],bbox[1],vertex))},measureCached$1=(geometry,measureFn)=>{let boundingBox=cache$2.get(geometry);return boundingBox||(boundingBox=measureFn(geometry),0===boundingBox.length&&(boundingBox[0]=[0,0,0],boundingBox[1]=[0,0,0]),cache$2.set(geometry,boundingBox),boundingBox)},measureBoundingBoxOfPath2=geometry=>{const boundingBox=[];return toPoints$1(geometry).forEach((point=>{expand2(boundingBox,point)})),boundingBox},measureBoundingBoxOfGeom2=geometry=>{const boundingBox=[];return toPoints$3(geometry).forEach((point=>{expand2(boundingBox,point)})),boundingBox},measureBoundingBoxOfGeom3=geometry=>{const boundingBox=[];return toPolygons$1(geometry).forEach((polygon=>{toVertices$1(polygon).forEach((vertex=>{expand3(boundingBox,vertex)}))})),boundingBox},measureBoundingBoxOfSlice=geometry=>{const boundingBox=[];return geometry.contours.forEach((contour=>{contour.forEach((vertex=>{expand3(boundingBox,vertex)}))})),boundingBox},measureBoundingBox=(...geometries)=>{if(0===(geometries=flatten$1(geometries)).length)throw new Error("wrong number of arguments");const results=geometries.map((geometry=>isA$2(geometry)?measureCached$1(geometry,measureBoundingBoxOfPath2):isA$5(geometry)?measureCached$1(geometry,measureBoundingBoxOfGeom2):isA$3(geometry)?measureCached$1(geometry,measureBoundingBoxOfGeom3):isA(geometry)?measureCached$1(geometry,measureBoundingBoxOfSlice):[[0,0,0],[0,0,0]]));return 1===results.length?results[0]:results},calculateEpsilonFromBounds=(bounds,dimensions)=>{let total=0;for(let i=0;i<dimensions;i++)total+=bounds[1][i]-bounds[0][i];return EPS*total/dimensions},createEdges=polygon=>{const vertices=toVertices$1(polygon),edges=[];for(let i=0;i<vertices.length;i++){const j=(i+1)%vertices.length,edge={v1:vertices[i],v2:vertices[j]};edges.push(edge)}for(let i=0;i<edges.length;i++){const j=(i+1)%vertices.length;edges[i].next=edges[j],edges[j].prev=edges[i]}return edges},insertEdge=(edges,edge)=>{const key=`${edge.v1}:${edge.v2}`;edges.set(key,edge)},deleteEdge=(edges,edge)=>{const key=`${edge.v1}:${edge.v2}`;edges.delete(key)},findOppositeEdge=(edges,edge)=>{const key=`${edge.v2}:${edge.v1}`;return edges.get(key)},calculateAnglesBetween=(current,opposite,normal)=>{let v0=current.prev.v1,v1=current.prev.v2,v2=opposite.next.v2;const angle1=calculateAngle(v0,v1,v2,normal);return v0=opposite.prev.v1,v1=opposite.prev.v2,v2=current.next.v2,[angle1,calculateAngle(v0,v1,v2,normal)]},v1=[0,0,0],v2=[0,0,0],calculateAngle=(prevVertex,midVertex,nextVertex,normal)=>{const d0=subtract$3(v1,midVertex,prevVertex),d1=subtract$3(v2,nextVertex,midVertex);return cross$1(d0,d0,d1),dot$2(d0,normal)},mergePolygons=(epsilon,polygons)=>{const polygonsPerPlane=[];polygons.forEach((polygon=>{const mapping=polygonsPerPlane.find((element=>{return plane1=element[0],plane2=plane(polygon),Math.abs(plane1[3]-plane2[3])<15e-8&&(a=plane1,b=plane2,Math.abs(a[0]-b[0])<=1e-13&&Math.abs(a[1]-b[1])<=1e-13&&Math.abs(a[2]-b[2])<=1e-13);var a,b,plane1,plane2}));mapping?mapping[1].push(polygon):polygonsPerPlane.push([plane(polygon),[polygon]])}));let destPolygons=[];return polygonsPerPlane.forEach((mapping=>{const retesselatedPolygons=(sourcePolygons=>{if(sourcePolygons.length<2)return sourcePolygons;const normal=sourcePolygons[0].plane,polygons=sourcePolygons.slice(),edgeList=new Map;for(;polygons.length>0;){const polygon=polygons.shift(),edges=createEdges(polygon);for(let i=0;i<edges.length;i++){const current=edges[i],opposite=findOppositeEdge(edgeList,current);if(opposite){const angles=calculateAnglesBetween(current,opposite,normal);if(angles[0]>=0&&angles[1]>=0){const edge1=opposite.next,edge2=current.next;current.prev.next=opposite.next,current.next.prev=opposite.prev,opposite.prev.next=current.next,opposite.next.prev=current.prev,current.v1=null,current.v2=null,current.next=null,current.prev=null,deleteEdge(edgeList,opposite),opposite.v1=null,opposite.v2=null,opposite.next=null,opposite.prev=null;const mergeEdges=(list,e1,e2)=>{const newEdge={v1:e2.v1,v2:e1.v2,next:e1.next,prev:e2.prev};e2.prev.next=newEdge,e1.next.prev=newEdge,deleteEdge(list,e1),e1.v1=null,e1.v2=null,e1.next=null,e1.prev=null,deleteEdge(list,e2),e2.v1=null,e2.v2=null,e2.next=null,e2.prev=null};0===angles[0]&&mergeEdges(edgeList,edge1,edge1.prev),0===angles[1]&&mergeEdges(edgeList,edge2,edge2.prev)}}else current.next&&insertEdge(edgeList,current)}}const destPolygons=[];return edgeList.forEach((edge=>{const polygon=(edge=>{let polygon;const vertices=[];for(;edge.next;){const next=edge.next;vertices.push(edge.v1),edge.v1=null,edge.v2=null,edge.next=null,edge.prev=null,edge=next}return vertices.length>0&&(polygon=create$7(vertices)),polygon})(edge);polygon&&destPolygons.push(polygon)})),edgeList.clear(),destPolygons})(mapping[1]);destPolygons=destPolygons.concat(retesselatedPolygons)})),destPolygons},getTag=vertex=>`${vertex}`,addSide=(sideMap,vertextag2sidestart,vertextag2sideend,vertex0,vertex1,polygonIndex)=>{const startTag=getTag(vertex0),endTag=getTag(vertex1),newSideTag=`${startTag}/${endTag}`,reverseSideTag=`${endTag}/${startTag}`;if(sideMap.has(reverseSideTag))return deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,vertex1,vertex0,null),null;const newSideObj={vertex0:vertex0,vertex1:vertex1,polygonIndex:polygonIndex};return sideMap.has(newSideTag)?sideMap.get(newSideTag).push(newSideObj):sideMap.set(newSideTag,[newSideObj]),vertextag2sidestart.has(startTag)?vertextag2sidestart.get(startTag).push(newSideTag):vertextag2sidestart.set(startTag,[newSideTag]),vertextag2sideend.has(endTag)?vertextag2sideend.get(endTag).push(newSideTag):vertextag2sideend.set(endTag,[newSideTag]),newSideTag},deleteSide=(sidemap,vertextag2sidestart,vertextag2sideend,vertex0,vertex1,polygonIndex)=>{const startTag=getTag(vertex0),endTag=getTag(vertex1),sideTag=`${startTag}/${endTag}`;let idx=-1;const sideObjs=sidemap.get(sideTag);for(let i=0;i<sideObjs.length;i++){const sideObj=sideObjs[i];let sideTag=getTag(sideObj.vertex0);if(sideTag===startTag&&(sideTag=getTag(sideObj.vertex1),sideTag===endTag&&(null===polygonIndex||sideObj.polygonIndex===polygonIndex))){idx=i;break}}sideObjs.splice(idx,1),0===sideObjs.length&&sidemap.delete(sideTag),idx=vertextag2sidestart.get(startTag).indexOf(sideTag),vertextag2sidestart.get(startTag).splice(idx,1),0===vertextag2sidestart.get(startTag).length&&vertextag2sidestart.delete(startTag),idx=vertextag2sideend.get(endTag).indexOf(sideTag),vertextag2sideend.get(endTag).splice(idx,1),0===vertextag2sideend.get(endTag).length&&vertextag2sideend.delete(endTag)},generalizeGeom3=(options,geometry)=>{const{snap:snap,simplify:simplify,triangulate:triangulate}=Object.assign({},{snap:!1,simplify:!1,triangulate:!1},options),epsilon=((...geometries)=>{if(0===(geometries=flatten$1(geometries)).length)throw new Error("wrong number of arguments");const results=geometries.map((geometry=>isA$2(geometry)||isA$5(geometry)?calculateEpsilonFromBounds(measureBoundingBox(geometry),2):isA$3(geometry)||isA(geometry)?calculateEpsilonFromBounds(measureBoundingBox(geometry),3):0));return 1===results.length?results[0]:results})(geometry);let polygons=toPolygons$1(geometry);snap&&(polygons=((epsilon,polygons)=>{let newPolygons=polygons.map((polygon=>{const snapVertices=polygon.vertices.map((vertex=>snap$2([0,0,0],vertex,epsilon))),newVertices=[];for(let i=0;i<snapVertices.length;i++){const j=(i+1)%snapVertices.length;equals$7(snapVertices[i],snapVertices[j])||newVertices.push(snapVertices[i])}const newPolygon=create$7(newVertices);return polygon.color&&(newPolygon.color=polygon.color),newPolygon}));const epsilonArea=epsilon*epsilon*Math.sqrt(3)/4;return newPolygons=newPolygons.filter((polygon=>((epsilon,polygon)=>{const area=Math.abs(measureArea$2(polygon));return Number.isFinite(area)&&area>epsilon})(epsilonArea,polygon))),newPolygons})(epsilon,polygons)),simplify&&(polygons=mergePolygons(0,polygons)),triangulate&&(polygons=(polygons=>{const sideMap=new Map;for(let polygonIndex=0;polygonIndex<polygons.length;polygonIndex++){const polygon=polygons[polygonIndex],numVertices=polygon.vertices.length;if(numVertices>=3){let vertex=polygon.vertices[0],vertexTag=getTag(vertex);for(let vertexIndex=0;vertexIndex<numVertices;vertexIndex++){let nextVertexIndex=vertexIndex+1;nextVertexIndex===numVertices&&(nextVertexIndex=0);const nextVertex=polygon.vertices[nextVertexIndex],nextVertexTag=getTag(nextVertex),sideTag=`${vertexTag}/${nextVertexTag}`,reverseSideTag=`${nextVertexTag}/${vertexTag}`;if(sideMap.has(reverseSideTag)){const ar=sideMap.get(reverseSideTag);ar.splice(-1,1),0===ar.length&&sideMap.delete(reverseSideTag)}else{const sideobj={vertex0:vertex,vertex1:nextVertex,polygonIndex:polygonIndex};sideMap.has(sideTag)?sideMap.get(sideTag).push(sideobj):sideMap.set(sideTag,[sideobj])}vertex=nextVertex,vertexTag=nextVertexTag}}else console.warn("warning: invalid polygon found during insertTjunctions")}if(sideMap.size>0){const vertextag2sidestart=new Map,vertextag2sideend=new Map,sidesToCheck=new Map;for(const[sidetag,sideObjs]of sideMap)sidesToCheck.set(sidetag,!0),sideObjs.forEach((sideObj=>{const starttag=getTag(sideObj.vertex0),endtag=getTag(sideObj.vertex1);vertextag2sidestart.has(starttag)?vertextag2sidestart.get(starttag).push(sidetag):vertextag2sidestart.set(starttag,[sidetag]),vertextag2sideend.has(endtag)?vertextag2sideend.get(endtag).push(sidetag):vertextag2sideend.set(endtag,[sidetag])}));const newPolygons=polygons.slice(0);for(;0!==sideMap.size;){for(const sideTag of sideMap.keys())sidesToCheck.set(sideTag,!0);let doneSomething=!1;for(;;){const sideTags=Array.from(sidesToCheck.keys());if(0===sideTags.length)break;const sideTagToCheck=sideTags[0];let doneWithSide=!0;if(sideMap.has(sideTagToCheck)){const sideObj=sideMap.get(sideTagToCheck)[0];for(let directionIndex=0;directionIndex<2;directionIndex++){const startVertex=0===directionIndex?sideObj.vertex0:sideObj.vertex1,endVertex=0===directionIndex?sideObj.vertex1:sideObj.vertex0,startVertexTag=getTag(startVertex),endVertexTag=getTag(endVertex);let matchingSides=[];0===directionIndex?vertextag2sideend.has(startVertexTag)&&(matchingSides=vertextag2sideend.get(startVertexTag)):vertextag2sidestart.has(startVertexTag)&&(matchingSides=vertextag2sidestart.get(startVertexTag));for(let matchingSideIndex=0;matchingSideIndex<matchingSides.length;matchingSideIndex++){const matchingSideTag=matchingSides[matchingSideIndex],matchingSide=sideMap.get(matchingSideTag)[0],matchingSideStartVertex=0===directionIndex?matchingSide.vertex0:matchingSide.vertex1;if(0===directionIndex?matchingSide.vertex1:matchingSide.vertex0,getTag(matchingSideStartVertex)===endVertexTag){deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,startVertex,endVertex,null),deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,endVertex,startVertex,null),doneWithSide=!1,directionIndex=2,doneSomething=!0;break}{const startPos=startVertex,endPos=endVertex,direction=subtract$3([0,0,0],matchingSideStartVertex,startPos),t=dot$2(subtract$3([0,0,0],endPos,startPos),direction)/dot$2(direction,direction);if(t>0&&t<1){const closestVertex=scale$3([0,0,0],direction,t);if(add$1(closestVertex,closestVertex,startPos),squaredDistance$1(closestVertex,endPos)<EPS*EPS){const polygonIndex=matchingSide.polygonIndex,polygon=newPolygons[polygonIndex],insertionVertexTag=getTag(matchingSide.vertex1);let insertionVertexTagIndex=-1;for(let i=0;i<polygon.vertices.length;i++)if(getTag(polygon.vertices[i])===insertionVertexTag){insertionVertexTagIndex=i;break}const newVertices=polygon.vertices.slice(0);newVertices.splice(insertionVertexTagIndex,0,endVertex);const newPolygon=create$7(newVertices);newPolygons[polygonIndex]=newPolygon,deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,matchingSide.vertex0,matchingSide.vertex1,polygonIndex);const newSideTag1=addSide(sideMap,vertextag2sidestart,vertextag2sideend,matchingSide.vertex0,endVertex,polygonIndex),newSideTag2=addSide(sideMap,vertextag2sidestart,vertextag2sideend,endVertex,matchingSide.vertex1,polygonIndex);null!==newSideTag1&&sidesToCheck.set(newSideTag1,!0),null!==newSideTag2&&sidesToCheck.set(newSideTag2,!0),doneWithSide=!1,directionIndex=2,doneSomething=!0;break}}}}}}doneWithSide&&sidesToCheck.delete(sideTagToCheck)}if(!doneSomething)break}polygons=newPolygons}return sideMap.clear(),polygons})(polygons),polygons=((epsilon,polygons)=>{const triangles=[];return polygons.forEach((polygon=>{((epsilon,polygon,triangles)=>{const nv=polygon.vertices.length;if(nv>3){if(nv>4){const midpoint=[0,0,0];polygon.vertices.forEach((vertex=>add$1(midpoint,midpoint,vertex))),snap$2(midpoint,divide$1(midpoint,midpoint,[nv,nv,nv]),epsilon);for(let i=0;i<nv;i++){const poly=create$7([midpoint,polygon.vertices[i],polygon.vertices[(i+1)%nv]]);polygon.color&&(poly.color=polygon.color),triangles.push(poly)}return}const poly0=create$7([polygon.vertices[0],polygon.vertices[1],polygon.vertices[2]]),poly1=create$7([polygon.vertices[0],polygon.vertices[2],polygon.vertices[3]]);return polygon.color&&(poly0.color=polygon.color,poly1.color=polygon.color),void triangles.push(poly0,poly1)}triangles.push(polygon)})(epsilon,polygon,triangles)})),triangles})(epsilon,polygons));const clone=Object.assign({},geometry);return clone.polygons=polygons,clone},flatten=arr=>arr.reduce(((acc,val)=>Array.isArray(val)?acc.concat(flatten(val)):acc.concat(val)),[]),stringify=(a,indentation)=>{const cr=indentation>0?"\n":"",indent=(indentation=>{if(!(indentation>0))return txt=>txt;const space=" ".repeat(indentation);return txt=>{if("string"!=typeof txt)return txt;const arr=txt.split("\n");return 1===arr.length?space+txt:arr.map((e=>""===e.trim()?e:space+e)).join("\n")}})(indentation),rec=a=>{let res,body="",isFlat=!0;return a.some(((e,i,arr)=>{if(0===i)return res="<"+e,1===arr.length;if(1===i){if((o=e)&&"[object Object]"===Object.prototype.toString.call(o))return Object.keys(e).forEach((key=>{let val=e[key];Array.isArray(val)&&(val=val.join(" ")),res+=" "+key+'="'+val+'"'})),2===arr.length||(res+=">",!1);res+=">"}var o;switch(typeof e){case"string":case"number":case"boolean":case"undefined":return body+=e+cr,!1}return isFlat=!1,body+=rec(e),!1}))?res+"/>"+cr:isFlat?res+body.split("\n").filter((e=>""!==e.trim())).join("\n")+"</"+a[0]+">"+cr:res+cr+indent(body)+"</"+a[0]+">"+cr};return rec(a)},defNames=new Map,convertObjects=(objects,options)=>{const shapes=[];return objects.forEach(((object,i)=>{options.statusCallback&&options.statusCallback({progress:100*i/objects.length}),index$6.isA(object)&&(object=((options,...geometries)=>{if(0===(geometries=flatten$1(geometries)).length)throw new Error("wrong number of arguments");const results=geometries.map((geometry=>{if(isA$2(geometry))return((options,geometry)=>geometry)(0,geometry);if(isA$5(geometry))return((options,geometry)=>geometry)(0,geometry);if(isA$3(geometry))return generalizeGeom3(options,geometry);throw new Error("invalid geometry")}));return 1===results.length?results[0]:results})({snap:!0,triangulate:!0},object),index$6.toPolygons(object).length>0&&shapes.push(convertGeom3(object,options))),index$a.isA(object)&&shapes.push(convertGeom2(object,options)),index$5.isA(object)&&shapes.push(convertPath2(object,options))})),[["Scene",{},["Transform",{rotation:"1 0 0 -1.5708"},...shapes]]]},convertPath2=(object,options)=>{const points=index$5.toPoints(object).slice();points.length>1&&object.isClosed&&points.push(points[0]);const shape=["Shape",shapeAttributes(object),convertPolyline2D(index$3.create(points))];return object.color&&shape.push(convertAppearance(object,"emissiveColor",options)),shape},convertGeom2=(object,options)=>{const outlines=index$a.toOutlines(object),group=["Group",{}];return outlines.forEach((outline=>{outline.length>1&&outline.push(outline[0]);const shape=["Shape",shapeAttributes(object),convertPolyline2D(index$3.create(outline))];object.color&&shape.push(convertAppearance(object,"emissiveColor",options)),group.push(shape)})),group},shapeAttributes=(object,attributes={})=>(object.id&&Object.assign(attributes,{DEF:checkDefName(object.id)}),attributes),checkDefName=defName=>{const count=defNames.get(defName)||0;return defNames.set(defName,count+1),count>0&&console.warn(`Warning: object.id set as DEF but not unique. ${defName} set ${count+1} times.`),defName},convertPolyline2D=(object,options)=>["Polyline2D",{lineSegments:object.points.map((p=>`${p[0]} ${p[1]}`)).join(" ")}],convertAppearance=(object,colorField,options)=>{const materialFields={[colorField]:object.color.slice(0,3).join(" "),transparency:roundToDecimals(1-object.color[3],options)};return"diffuseColor"===colorField&&Object.assign(materialFields,{specularColor:"0.2 0.2 0.2",shininess:options.shininess}),["Appearance",["Material",materialFields]]},convertGeom3=(object,options)=>{const shape=["Shape",shapeAttributes(object),convertMesh(object,options)];let appearance=["Appearance",{},["Material"]];return object.color&&(appearance=convertAppearance(object,"diffuseColor",options)),shape.push(appearance),shape},convertMesh=(object,options)=>{const mesh=convertToTriangles(object,options),lists=polygons2coordinates(mesh,options),indexList=lists[0].join(" "),pointList=lists[1].join(" "),colorList=lists[2].join(" "),faceset=["IndexedTriangleSet",{ccw:"true",colorPerVertex:"false",normalPerVertex:options.smooth,solid:"false",index:indexList},["Coordinate",{point:pointList}]];return object.color||faceset.push(["Color",{color:colorList}]),faceset},convertToTriangles=(object,options)=>{const triangles=[];return index$6.toPolygons(object).forEach((poly=>{const firstVertex=poly.vertices[0];for(let i=poly.vertices.length-3;i>=0;i--){const triangle=index$7.create([firstVertex,poly.vertices[i+1],poly.vertices[i+2]]);let color=options.color;object.color&&(color=object.color),poly.color&&(color=poly.color),triangle.color=color,triangles.push(triangle)}})),triangles},roundToDecimals=(float,options)=>Math.round(float*options.decimals)/options.decimals,polygons2coordinates=(polygons,options)=>{const indexList=[],pointList=[],colorList=[],vertexTagToCoordIndexMap=new Map;return polygons.forEach((polygon=>{const polygonVertexIndices=[],numvertices=polygon.vertices.length;for(let i=0;i<numvertices;i++){const vertex=polygon.vertices[i],id=`${vertex[0]},${vertex[1]},${vertex[2]}`;if(!vertexTagToCoordIndexMap.has(id)){const x=roundToDecimals(vertex[0],options),y=roundToDecimals(vertex[1],options),z=roundToDecimals(vertex[2],options);pointList.push(`${x} ${y} ${z}`),vertexTagToCoordIndexMap.set(id,pointList.length-1)}polygonVertexIndices.push(vertexTagToCoordIndexMap.get(id))}indexList.push(polygonVertexIndices.join(" ")),colorList.push(((polygon,options)=>{let color=options.color;return polygon.color&&(color=polygon.color),`${color[0]} ${color[1]} ${color[2]}`})(polygon,options))})),vertexTagToCoordIndexMap.clear(),[indexList,pointList,colorList]};exports.mimeType="model/x3d+xml",exports.serialize=(options,...objects)=>{if(options=Object.assign({},{color:[0,0,1,1],shininess:8/256,smooth:!1,decimals:1e3,metadata:!0,unit:"millimeter",statusCallback:null},options),0===(objects=(objects=flatten(objects)).filter((object=>index$6.isA(object)||index$a.isA(object)||index$5.isA(object)))).length)throw new Error("expected one or more geom3/geom2/path2 objects");options.statusCallback&&options.statusCallback({progress:0});let body=["X3D",{profile:"Interchange",version:"3.3","xmlns:xsd":"http://www.w3.org/2001/XMLSchema-instance","xsd:noNamespaceSchemaLocation":"http://www.web3d.org/specifications/x3d-3.3.xsd"}];options.metadata?body.push(["head",{},["meta",{name:"creator",content:"Created by JSCAD"}],["meta",{name:"reference",content:"https://www.openjscad.xyz"}],["meta",{name:"created",content:(new Date).toISOString()}]]):body.push(["head",{},["meta",{name:"creator",content:"Created by JSCAD"}]]),body=body.concat(convertObjects(objects,options));const contents=`<?xml version="1.0" encoding="UTF-8"?>\n${stringify(body,2)}`;return options&&options.statusCallback&&options.statusCallback({progress:100}),[contents]},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).jscadX3dSerializer={});
package/package.json CHANGED
@@ -1,26 +1,31 @@
1
1
  {
2
2
  "name": "@jscad/x3d-serializer",
3
- "version": "2.4.5",
3
+ "version": "3.0.0-alpha.0",
4
4
  "description": "X3D Serializer for JSCAD",
5
5
  "homepage": "https://openjscad.xyz/",
6
6
  "repository": "https://github.com/jscad/OpenJSCAD.org",
7
+ "type": "module",
7
8
  "main": "src/index.js",
9
+ "unpkg": "dist/jscad-x3d-serializer.min.js",
10
+ "module": "dist/jscad-x3d-serializer.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,13 +37,18 @@
32
37
  ],
33
38
  "license": "MIT",
34
39
  "dependencies": {
35
- "@jscad/array-utils": "2.1.4",
36
- "@jscad/modeling": "2.12.0",
37
- "onml": "1.3.0"
40
+ "@jscad/array-utils": "3.0.0-alpha.0",
41
+ "@jscad/io-utils": "^3.0.0-alpha.0",
42
+ "@jscad/modeling": "3.0.0-alpha.0",
43
+ "onml": "^1.3.0"
38
44
  },
39
45
  "devDependencies": {
40
- "ava": "3.15.0",
41
- "nyc": "15.1.0"
46
+ "@rollup/plugin-node-resolve": "^15.0.1",
47
+ "@rollup/plugin-terser": "^0.4.3",
48
+ "ava": "^4.3.3",
49
+ "c8": "^8.0.0",
50
+ "rollup": "^2.79.1",
51
+ "rollup-plugin-banner": "^0.2.1"
42
52
  },
43
- "gitHead": "e269f212db5a00cda740d2f7ad3e5206d1eb839f"
53
+ "gitHead": "3656d36ed9cd738ab884e86aae5a2ce08d52adf7"
44
54
  }
@@ -0,0 +1,25 @@
1
+ import banner from 'rollup-plugin-banner'
2
+ import { nodeResolve } from '@rollup/plugin-node-resolve'
3
+ import terser from '@rollup/plugin-terser'
4
+
5
+ export default {
6
+ input: 'src/index.js',
7
+
8
+ output: [
9
+ {
10
+ file: 'dist/jscad-x3d-serializer.min.js',
11
+ format: 'umd',
12
+ name: 'jscadX3dSerializer'
13
+ },
14
+ {
15
+ file: 'dist/jscad-x3d-serializer.es.js',
16
+ format: 'es'
17
+ }
18
+ ],
19
+
20
+ plugins: [
21
+ nodeResolve(),
22
+ banner('<%= pkg.description %>\n@module <%= pkg.name %>\n@version <%= pkg.version %>\n@license <%= pkg.license %>'),
23
+ terser({ compress: { module: true }, mangle: false, format: { comments: 'some'} })
24
+ ]
25
+ }
package/src/index.js CHANGED
@@ -1,20 +1,8 @@
1
- /*
2
- JSCAD Object to X3D (XML) Format Serialization
3
-
4
- ## License
1
+ import { generalize, geom2, geom3, path2, poly2, poly3 } from '@jscad/modeling'
5
2
 
6
- Copyright (c) 2018-2022 JSCAD Organization https://github.com/jscad
3
+ import { flatten } from '@jscad/array-utils'
7
4
 
8
- All code released under MIT license
9
-
10
- Notes:
11
- 1) geom2 conversion to:
12
- Polyline2D with lineSegment and Color
13
- 2) geom3 conversion to:
14
- IndexedTriangleSet with Coordinates and Colors
15
- 3) path2 conversion to:
16
- Polyline2D with lineSegment and Color
17
- */
5
+ import { stringify } from '@jscad/io-utils'
18
6
 
19
7
  /**
20
8
  * Serializer of JSCAD geometries to X3D source data (XML).
@@ -31,17 +19,6 @@ Notes:
31
19
  * const { serializer, mimeType } = require('@jscad/x3d-serializer')
32
20
  */
33
21
 
34
- const { geometries, modifiers } = require('@jscad/modeling')
35
- const { geom2, geom3, path2, poly2, poly3 } = geometries
36
-
37
- const { flatten } = require('@jscad/array-utils')
38
-
39
- const stringify = require('onml/lib/stringify')
40
-
41
- // http://www.web3d.org/x3d/content/X3dTooltips.html
42
- // http://www.web3d.org/x3d/content/examples/X3dSceneAuthoringHints.html#Meshes
43
- // https://x3dgraphics.com/examples/X3dForWebAuthors/Chapter13GeometryTrianglesQuadrilaterals/
44
-
45
22
  const mimeType = 'model/x3d+xml'
46
23
  const defNames = new Map()
47
24
 
@@ -120,7 +97,7 @@ const convertObjects = (objects, options) => {
120
97
 
121
98
  if (geom3.isA(object)) {
122
99
  // convert to triangles
123
- object = modifiers.generalize({ snap: true, triangulate: true }, object)
100
+ object = generalize({ snap: true, triangulate: true }, object)
124
101
  const polygons = geom3.toPolygons(object)
125
102
  if (polygons.length > 0) {
126
103
  shapes.push(convertGeom3(object, options))
@@ -190,7 +167,7 @@ const checkDefName = (defName) => {
190
167
  * Convert the given object (poly2) to X3D source
191
168
  */
192
169
  const convertPolyline2D = (object, options) => {
193
- const lineSegments = object.vertices.map((p) => `${p[0]} ${p[1]}`).join(' ')
170
+ const lineSegments = object.points.map((p) => `${p[0]} ${p[1]}`).join(' ')
194
171
  return ['Polyline2D', { lineSegments }]
195
172
  }
196
173
 
@@ -248,7 +225,7 @@ const convertToTriangles = (object, options) => {
248
225
  polygons.forEach((poly) => {
249
226
  const firstVertex = poly.vertices[0]
250
227
  for (let i = poly.vertices.length - 3; i >= 0; i--) {
251
- const triangle = poly3.fromPoints([
228
+ const triangle = poly3.create([
252
229
  firstVertex,
253
230
  poly.vertices[i + 1],
254
231
  poly.vertices[i + 2]
@@ -312,7 +289,7 @@ const polygons2coordinates = (polygons, options) => {
312
289
  return [indexList, pointList, colorList]
313
290
  }
314
291
 
315
- module.exports = {
316
- serialize,
317
- mimeType
292
+ export {
293
+ mimeType,
294
+ serialize
318
295
  }
@@ -1,13 +1,13 @@
1
- const test = require('ava')
1
+ import test from 'ava'
2
2
 
3
- const countOf = require('../../test/helpers/countOf')
3
+ import { countOf } from '../../test/helpers/countOf.js'
4
4
 
5
- const { colors, geometries, primitives } = require('@jscad/modeling')
5
+ import { colorize, geom2, rectangle } from '@jscad/modeling'
6
6
 
7
- const { serialize } = require('../src/index.js')
7
+ import { serialize } from '../src/index.js'
8
8
 
9
9
  test('serialize 2D geometry to X3D Polyline2D', (t) => {
10
- const shape1 = geometries.geom2.create()
10
+ const shape1 = geom2.create()
11
11
 
12
12
  let results = serialize({}, shape1)
13
13
  t.is(results.length, 1)
@@ -22,7 +22,7 @@ test('serialize 2D geometry to X3D Polyline2D', (t) => {
22
22
  t.is(countOf('Scene', obs), 2)
23
23
  t.is(countOf('Group', obs), 1)
24
24
 
25
- const shape2 = primitives.rectangle()
25
+ const shape2 = rectangle()
26
26
 
27
27
  results = serialize({ metadata: false }, shape2)
28
28
  t.is(results.length, 1)
@@ -39,7 +39,7 @@ test('serialize 2D geometry to X3D Polyline2D', (t) => {
39
39
  t.is(countOf('Shape', obs), 2)
40
40
  t.is(countOf('Polyline2D', obs), 1)
41
41
 
42
- const shape3 = colors.colorize([0, 0, 0], shape2)
42
+ const shape3 = colorize([0, 0, 0], shape2)
43
43
 
44
44
  results = serialize({ metadata: false }, shape3)
45
45
  t.is(results.length, 1)
@@ -1,15 +1,15 @@
1
- const test = require('ava')
1
+ import test from 'ava'
2
2
 
3
- const countOf = require('../../test/helpers/countOf')
3
+ import { countOf } from '../../test/helpers/countOf.js'
4
4
 
5
- const { colors, geometries, primitives, transforms } = require('@jscad/modeling')
5
+ import { center, colorize, cube, geom3 } from '@jscad/modeling'
6
6
 
7
- const serializer = require('../src/index.js')
7
+ import { serialize } from '../src/index.js'
8
8
 
9
9
  test('serialize 3D geometry to X3D IndexedTriangleSet', (t) => {
10
- const geom1 = geometries.geom3.create()
10
+ const g1 = geom3.create()
11
11
 
12
- let results = serializer.serialize({}, geom1)
12
+ let results = serialize({}, g1)
13
13
  t.is(results.length, 1)
14
14
 
15
15
  let obs = results[0]
@@ -21,9 +21,9 @@ test('serialize 3D geometry to X3D IndexedTriangleSet', (t) => {
21
21
  t.is(countOf('Created by JSCAD', obs), 1)
22
22
  t.is(countOf('Scene', obs), 2)
23
23
 
24
- const geom2 = primitives.cube()
24
+ const g2 = cube()
25
25
 
26
- results = serializer.serialize({ metadata: false }, geom2)
26
+ results = serialize({ metadata: false }, g2)
27
27
  t.is(results.length, 1)
28
28
 
29
29
  obs = results[0]
@@ -41,10 +41,10 @@ test('serialize 3D geometry to X3D IndexedTriangleSet', (t) => {
41
41
  t.is(countOf('Coordinate', obs), 1)
42
42
  t.is(countOf('Color', obs), 1)
43
43
 
44
- const geom3 = colors.colorize([0.5, 1, 0.5, 1.0], transforms.center({ relativeTo: [5, 5, 5] }, primitives.cube()))
45
- geom2.id = geom3.id = 'g23'
44
+ const g3 = colorize([0.5, 1, 0.5, 1.0], center({ relativeTo: [5, 5, 5] }, cube()))
45
+ g2.id = g3.id = 'g23'
46
46
 
47
- results = serializer.serialize({ metadata: false }, geom2, geom3)
47
+ results = serialize({ metadata: false }, g2, g3)
48
48
  t.is(results.length, 1)
49
49
 
50
50
  obs = results[0]
@@ -1,15 +1,15 @@
1
- const test = require('ava')
1
+ import test from 'ava'
2
2
 
3
- const countOf = require('../../test/helpers/countOf')
3
+ import { countOf } from '../../test/helpers/countOf.js'
4
4
 
5
- const { colors, geometries, primitives } = require('@jscad/modeling')
5
+ import { arc, colorize, path2 } from '@jscad/modeling'
6
6
 
7
- const { serialize } = require('../src/index.js')
7
+ import { serialize } from '../src/index.js'
8
8
 
9
9
  test('serialize 2D path to X3D Polyline2D', (t) => {
10
- const path1 = geometries.path2.create()
10
+ const p1 = path2.create()
11
11
 
12
- let results = serialize({}, path1)
12
+ let results = serialize({}, p1)
13
13
  t.is(results.length, 1)
14
14
 
15
15
  let obs = results[0]
@@ -20,9 +20,9 @@ test('serialize 2D path to X3D Polyline2D', (t) => {
20
20
  t.is(countOf('content', obs), 3)
21
21
  t.is(countOf('Created by JSCAD', obs), 1)
22
22
 
23
- const path2 = primitives.arc({ center: [5, 5], endAngle: 45, segments: 16 })
23
+ const p2 = arc({ center: [5, 5], endAngle: 45, segments: 16 })
24
24
 
25
- results = serialize({ metadata: false }, path2)
25
+ results = serialize({ metadata: false }, p2)
26
26
  t.is(results.length, 1)
27
27
 
28
28
  obs = results[0]
@@ -33,9 +33,9 @@ test('serialize 2D path to X3D Polyline2D', (t) => {
33
33
  t.is(countOf('Polyline2D', obs), 1)
34
34
  t.is(countOf('lineSegments', obs), 1)
35
35
 
36
- const path3 = colors.colorize([0, 0, 0], path2)
36
+ const p3 = colorize([0, 0, 0], p2)
37
37
 
38
- results = serialize({ metadata: false }, path2, path3)
38
+ results = serialize({ metadata: false }, p2, p3)
39
39
  t.is(results.length, 1)
40
40
 
41
41
  obs = results[0]