3dtiles-inspector 0.1.5 → 0.1.7

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
@@ -6,6 +6,19 @@ The format is based on Keep a Changelog and this project follows Semantic Versio
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.1.7] - 2026-04-27
10
+
11
+ ### Changed
12
+
13
+ - Changed `Layer Multiplier` to use the tileset-wide minimum leaf geometric error as the baseline, so non-minimum leaf tiles are scaled too.
14
+
15
+ ## [0.1.6] - 2026-04-27
16
+
17
+ ### Changed
18
+
19
+ - Changed `Layer Multiplier` to scale each tile's geometric-error difference from its leaf baseline instead of applying a depth-based multiplier.
20
+ - Expanded the `Layer Multiplier` range to `1/8x` through `8x`.
21
+
9
22
  ## [0.1.5] - 2026-04-27
10
23
 
11
24
  ### Added
package/README.md CHANGED
@@ -76,13 +76,15 @@ const {
76
76
 
77
77
  ## Inspector Features
78
78
 
79
+ <img src="https://raw.githubusercontent.com/WilliamLiu-1997/3DTiles-Inspector/main/screenshot.png" alt="screenshot" width="960" />
80
+
79
81
  - `Translate`, `Rotate`, and `Reset` for root transform edits
80
82
  - `Move Camera` to a WGS84 latitude / longitude / height
81
83
  - `Move Tiles` to relocate the tileset root with an ENU-aligned transform
82
84
  - `Set Position` to click the globe, terrain, or loaded tiles and place the tileset there
83
85
  - `Terrain` to toggle Cesium World Terrain while keeping satellite imagery
84
86
  - `Geometric Error` scaling from `1/16x` to `16x`
85
- - `Layer Multiplier` scaling from `1/1.5x` to `1.5x` for leaf-based geometric error changes between tile depths
87
+ - `Layer Multiplier` scaling from `1/8x` to `8x` for each tile's geometric-error difference from the tileset's global leaf baseline
86
88
  - `Save` to persist the updated root transform and geometric-error scale back to disk
87
89
 
88
90
  If `build_summary.json` exists next to the root tileset, `Save` also updates:
@@ -65496,14 +65496,9 @@ var saveButton = document.getElementById("save");
65496
65496
  var GEOMETRIC_ERROR_SCALE_MIN_EXPONENT = -4;
65497
65497
  var GEOMETRIC_ERROR_SCALE_MAX_EXPONENT = 4;
65498
65498
  var GEOMETRIC_ERROR_SCALE_STEP = 0.1;
65499
- var GEOMETRIC_ERROR_LAYER_SCALE_MAX = 1.5;
65500
- var GEOMETRIC_ERROR_LAYER_SCALE_MIN_EXPONENT = -Math.log2(
65501
- GEOMETRIC_ERROR_LAYER_SCALE_MAX
65502
- );
65503
- var GEOMETRIC_ERROR_LAYER_SCALE_MAX_EXPONENT = Math.log2(
65504
- GEOMETRIC_ERROR_LAYER_SCALE_MAX
65505
- );
65506
- var GEOMETRIC_ERROR_LAYER_SCALE_STEP = "any";
65499
+ var GEOMETRIC_ERROR_LAYER_SCALE_MIN_EXPONENT = -3;
65500
+ var GEOMETRIC_ERROR_LAYER_SCALE_MAX_EXPONENT = 3;
65501
+ var GEOMETRIC_ERROR_LAYER_SCALE_STEP = 0.1;
65507
65502
  var DEFAULT_ERROR_TARGET = 16;
65508
65503
  var DEFAULT_TERRAIN_ERROR_TARGET = 16;
65509
65504
  var RUNTIME_STATS_UPDATE_INTERVAL_MS = 250;
@@ -65860,22 +65855,6 @@ function getEffectiveGeometricErrorScale() {
65860
65855
  function getEffectiveGeometricErrorLayerScale() {
65861
65856
  return lastSavedGeometricErrorLayerScale * geometricErrorLayerScale;
65862
65857
  }
65863
- function getKnownTileLeafDistance(tile, visited = /* @__PURE__ */ new Set()) {
65864
- if (!tile || typeof tile !== "object" || visited.has(tile)) {
65865
- return 0;
65866
- }
65867
- visited.add(tile);
65868
- let maxDistance = 0;
65869
- const children = Array.isArray(tile.children) ? tile.children : [];
65870
- for (const child of children) {
65871
- maxDistance = Math.max(
65872
- maxDistance,
65873
- getKnownTileLeafDistance(child, visited) + 1
65874
- );
65875
- }
65876
- visited.delete(tile);
65877
- return maxDistance;
65878
- }
65879
65858
  function getOriginalTileGeometricError(tile) {
65880
65859
  if (!tile || typeof tile !== "object") {
65881
65860
  return null;
@@ -65889,21 +65868,52 @@ function getOriginalTileGeometricError(tile) {
65889
65868
  }
65890
65869
  return originalTileGeometricErrors.get(tile);
65891
65870
  }
65892
- function applyGeometricErrorLayerScaleToTile(tile) {
65871
+ function getKnownTileLeafGeometricError(tile, visited = /* @__PURE__ */ new Set()) {
65872
+ const originalGeometricError = getOriginalTileGeometricError(tile);
65873
+ if (originalGeometricError === null || !tile || typeof tile !== "object" || visited.has(tile)) {
65874
+ return originalGeometricError;
65875
+ }
65876
+ visited.add(tile);
65877
+ let leafGeometricError = null;
65878
+ const children = Array.isArray(tile.children) ? tile.children : [];
65879
+ for (const child of children) {
65880
+ const childLeafGeometricError = getKnownTileLeafGeometricError(
65881
+ child,
65882
+ visited
65883
+ );
65884
+ if (childLeafGeometricError !== null) {
65885
+ leafGeometricError = leafGeometricError === null ? childLeafGeometricError : Math.min(leafGeometricError, childLeafGeometricError);
65886
+ }
65887
+ }
65888
+ visited.delete(tile);
65889
+ return leafGeometricError === null ? originalGeometricError : leafGeometricError;
65890
+ }
65891
+ function getGlobalTileLeafGeometricError(tile) {
65892
+ const rootLeafGeometricError = tiles?.root ? getKnownTileLeafGeometricError(tiles.root) : null;
65893
+ const tileLeafGeometricError = getKnownTileLeafGeometricError(tile);
65894
+ if (rootLeafGeometricError === null) {
65895
+ return tileLeafGeometricError;
65896
+ }
65897
+ if (tileLeafGeometricError === null) {
65898
+ return rootLeafGeometricError;
65899
+ }
65900
+ return Math.min(rootLeafGeometricError, tileLeafGeometricError);
65901
+ }
65902
+ function applyGeometricErrorLayerScaleToTile(tile, leafGeometricError = getGlobalTileLeafGeometricError(tile)) {
65893
65903
  const originalGeometricError = getOriginalTileGeometricError(tile);
65894
- if (originalGeometricError === null) {
65904
+ if (originalGeometricError === null || leafGeometricError === null) {
65895
65905
  return;
65896
65906
  }
65897
- const leafDistance = getKnownTileLeafDistance(tile);
65898
- tile.geometricError = originalGeometricError * getEffectiveGeometricErrorLayerScale() ** leafDistance;
65907
+ tile.geometricError = leafGeometricError + (originalGeometricError - leafGeometricError) * getEffectiveGeometricErrorLayerScale();
65899
65908
  }
65900
65909
  function applyGeometricErrorLayerScaleToTileset() {
65901
65910
  if (!tiles) {
65902
65911
  return;
65903
65912
  }
65913
+ const leafGeometricError = getGlobalTileLeafGeometricError(tiles.root);
65904
65914
  tiles.traverse(
65905
65915
  (tile) => {
65906
- applyGeometricErrorLayerScaleToTile(tile);
65916
+ applyGeometricErrorLayerScaleToTile(tile, leafGeometricError);
65907
65917
  return false;
65908
65918
  },
65909
65919
  null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "3dtiles-inspector",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Inspect, align, and save local 3D Tiles root transforms in an interactive browser session.",
5
5
  "author": "William Liu <lyz15972107087@gmail.com>",
6
6
  "license": "Apache-2.0",
package/src/viewer/app.js CHANGED
@@ -112,14 +112,9 @@ const saveButton = document.getElementById('save');
112
112
  const GEOMETRIC_ERROR_SCALE_MIN_EXPONENT = -4;
113
113
  const GEOMETRIC_ERROR_SCALE_MAX_EXPONENT = 4;
114
114
  const GEOMETRIC_ERROR_SCALE_STEP = 0.1;
115
- const GEOMETRIC_ERROR_LAYER_SCALE_MAX = 1.5;
116
- const GEOMETRIC_ERROR_LAYER_SCALE_MIN_EXPONENT = -Math.log2(
117
- GEOMETRIC_ERROR_LAYER_SCALE_MAX,
118
- );
119
- const GEOMETRIC_ERROR_LAYER_SCALE_MAX_EXPONENT = Math.log2(
120
- GEOMETRIC_ERROR_LAYER_SCALE_MAX,
121
- );
122
- const GEOMETRIC_ERROR_LAYER_SCALE_STEP = 'any';
115
+ const GEOMETRIC_ERROR_LAYER_SCALE_MIN_EXPONENT = -3;
116
+ const GEOMETRIC_ERROR_LAYER_SCALE_MAX_EXPONENT = 3;
117
+ const GEOMETRIC_ERROR_LAYER_SCALE_STEP = 0.1;
123
118
  const DEFAULT_ERROR_TARGET = 16;
124
119
  const DEFAULT_TERRAIN_ERROR_TARGET = 16;
125
120
  const RUNTIME_STATS_UPDATE_INTERVAL_MS = 250;
@@ -537,24 +532,6 @@ function getEffectiveGeometricErrorLayerScale() {
537
532
  return lastSavedGeometricErrorLayerScale * geometricErrorLayerScale;
538
533
  }
539
534
 
540
- function getKnownTileLeafDistance(tile, visited = new Set()) {
541
- if (!tile || typeof tile !== 'object' || visited.has(tile)) {
542
- return 0;
543
- }
544
-
545
- visited.add(tile);
546
- let maxDistance = 0;
547
- const children = Array.isArray(tile.children) ? tile.children : [];
548
- for (const child of children) {
549
- maxDistance = Math.max(
550
- maxDistance,
551
- getKnownTileLeafDistance(child, visited) + 1,
552
- );
553
- }
554
- visited.delete(tile);
555
- return maxDistance;
556
- }
557
-
558
535
  function getOriginalTileGeometricError(tile) {
559
536
  if (!tile || typeof tile !== 'object') {
560
537
  return null;
@@ -571,16 +548,68 @@ function getOriginalTileGeometricError(tile) {
571
548
  return originalTileGeometricErrors.get(tile);
572
549
  }
573
550
 
574
- function applyGeometricErrorLayerScaleToTile(tile) {
551
+ function getKnownTileLeafGeometricError(tile, visited = new Set()) {
552
+ const originalGeometricError = getOriginalTileGeometricError(tile);
553
+ if (
554
+ originalGeometricError === null ||
555
+ !tile ||
556
+ typeof tile !== 'object' ||
557
+ visited.has(tile)
558
+ ) {
559
+ return originalGeometricError;
560
+ }
561
+
562
+ visited.add(tile);
563
+ let leafGeometricError = null;
564
+ const children = Array.isArray(tile.children) ? tile.children : [];
565
+ for (const child of children) {
566
+ const childLeafGeometricError = getKnownTileLeafGeometricError(
567
+ child,
568
+ visited,
569
+ );
570
+ if (childLeafGeometricError !== null) {
571
+ leafGeometricError =
572
+ leafGeometricError === null
573
+ ? childLeafGeometricError
574
+ : Math.min(leafGeometricError, childLeafGeometricError);
575
+ }
576
+ }
577
+ visited.delete(tile);
578
+ return leafGeometricError === null
579
+ ? originalGeometricError
580
+ : leafGeometricError;
581
+ }
582
+
583
+ function getGlobalTileLeafGeometricError(tile) {
584
+ const rootLeafGeometricError = tiles?.root
585
+ ? getKnownTileLeafGeometricError(tiles.root)
586
+ : null;
587
+ const tileLeafGeometricError = getKnownTileLeafGeometricError(tile);
588
+
589
+ if (rootLeafGeometricError === null) {
590
+ return tileLeafGeometricError;
591
+ }
592
+
593
+ if (tileLeafGeometricError === null) {
594
+ return rootLeafGeometricError;
595
+ }
596
+
597
+ return Math.min(rootLeafGeometricError, tileLeafGeometricError);
598
+ }
599
+
600
+ function applyGeometricErrorLayerScaleToTile(
601
+ tile,
602
+ leafGeometricError = getGlobalTileLeafGeometricError(tile),
603
+ ) {
575
604
  const originalGeometricError = getOriginalTileGeometricError(tile);
576
- if (originalGeometricError === null) {
605
+ if (originalGeometricError === null || leafGeometricError === null) {
577
606
  return;
578
607
  }
579
608
 
580
- const leafDistance = getKnownTileLeafDistance(tile);
581
609
  tile.geometricError =
582
- originalGeometricError *
583
- getEffectiveGeometricErrorLayerScale() ** leafDistance;
610
+ leafGeometricError +
611
+ (originalGeometricError - leafGeometricError) *
612
+ getEffectiveGeometricErrorLayerScale();
584
613
  }
585
614
 
586
615
  function applyGeometricErrorLayerScaleToTileset() {
@@ -588,9 +617,10 @@ function applyGeometricErrorLayerScaleToTileset() {
588
617
  return;
589
618
  }
590
619
 
620
+ const leafGeometricError = getGlobalTileLeafGeometricError(tiles.root);
591
621
  tiles.traverse(
592
622
  (tile) => {
593
- applyGeometricErrorLayerScaleToTile(tile);
623
+ applyGeometricErrorLayerScaleToTile(tile, leafGeometricError);
594
624
  return false;
595
625
  },
596
626
  null,
@@ -174,7 +174,14 @@ function normalizePositiveFinite(value, name) {
174
174
  return number;
175
175
  }
176
176
 
177
- function scaleGeometricErrorValue(target, key, scale, label) {
177
+ function scaleGeometricErrorValue(
178
+ target,
179
+ key,
180
+ geometricErrorScale,
181
+ geometricErrorLayerScale,
182
+ leafGeometricError,
183
+ label,
184
+ ) {
178
185
  if (target[key] == null) {
179
186
  return;
180
187
  }
@@ -184,7 +191,14 @@ function scaleGeometricErrorValue(target, key, scale, label) {
184
191
  throw new InspectorError(`${label} must be a finite number.`);
185
192
  }
186
193
 
187
- const next = number * scale;
194
+ if (!Number.isFinite(leafGeometricError)) {
195
+ throw new InspectorError(`${label} leaf geometricError must be finite.`);
196
+ }
197
+
198
+ const adjusted =
199
+ leafGeometricError +
200
+ (number - leafGeometricError) * geometricErrorLayerScale;
201
+ const next = adjusted * geometricErrorScale;
188
202
  if (!Number.isFinite(next)) {
189
203
  throw new InspectorError(`${label} scaled value must be finite.`);
190
204
  }
@@ -192,20 +206,6 @@ function scaleGeometricErrorValue(target, key, scale, label) {
192
206
  target[key] = next;
193
207
  }
194
208
 
195
- function getGeometricErrorScaleForLeafDistance(
196
- geometricErrorScale,
197
- geometricErrorLayerScale,
198
- leafDistance,
199
- label,
200
- ) {
201
- const scale =
202
- geometricErrorScale * geometricErrorLayerScale ** Math.max(0, leafDistance);
203
- if (!Number.isFinite(scale)) {
204
- throw new InspectorError(`${label} scale must be a finite number.`);
205
- }
206
- return scale;
207
- }
208
-
209
209
  function assertTilesetPathInsideRoot(resolvedPath, rootDir) {
210
210
  if (
211
211
  resolvedPath !== rootDir &&
@@ -250,15 +250,15 @@ function getLocalExternalTilesetPaths(tile, baseDir) {
250
250
  return paths;
251
251
  }
252
252
 
253
- function getTilesetRootLeafDistance(
253
+ function getTilesetRootLeafGeometricError(
254
254
  tilesetPath,
255
255
  rootDir,
256
- leafDistanceCache,
256
+ leafGeometricErrorCache,
257
257
  stack,
258
258
  ) {
259
259
  const resolvedPath = path.resolve(tilesetPath);
260
- if (leafDistanceCache.has(resolvedPath)) {
261
- return leafDistanceCache.get(resolvedPath);
260
+ if (leafGeometricErrorCache.has(resolvedPath)) {
261
+ return leafGeometricErrorCache.get(resolvedPath);
262
262
  }
263
263
 
264
264
  if (stack.has(resolvedPath)) {
@@ -279,56 +279,72 @@ function getTilesetRootLeafDistance(
279
279
  }
280
280
 
281
281
  stack.add(resolvedPath);
282
- const leafDistance = getTileLeafDistance(
282
+ const leafGeometricError = getTileLeafGeometricError(
283
283
  tileset.root,
284
284
  path.dirname(resolvedPath),
285
285
  rootDir,
286
- leafDistanceCache,
286
+ leafGeometricErrorCache,
287
287
  stack,
288
288
  );
289
289
  stack.delete(resolvedPath);
290
- leafDistanceCache.set(resolvedPath, leafDistance);
291
- return leafDistance;
290
+ leafGeometricErrorCache.set(resolvedPath, leafGeometricError);
291
+ return leafGeometricError;
292
292
  }
293
293
 
294
- function getTileLeafDistance(tile, baseDir, rootDir, leafDistanceCache, stack) {
294
+ function getTileLeafGeometricError(
295
+ tile,
296
+ baseDir,
297
+ rootDir,
298
+ leafGeometricErrorCache,
299
+ stack,
300
+ ) {
295
301
  if (!tile || typeof tile !== 'object') {
296
302
  return 0;
297
303
  }
298
304
 
299
- let maxDistance = 0;
305
+ const ownGeometricError = Number(tile.geometricError);
306
+ if (!Number.isFinite(ownGeometricError)) {
307
+ return 0;
308
+ }
309
+
310
+ let leafGeometricError = null;
300
311
  if (Array.isArray(tile.children)) {
301
312
  tile.children.forEach((child) => {
302
- maxDistance = Math.max(
303
- maxDistance,
304
- getTileLeafDistance(child, baseDir, rootDir, leafDistanceCache, stack) +
305
- 1,
313
+ const childLeafGeometricError = getTileLeafGeometricError(
314
+ child,
315
+ baseDir,
316
+ rootDir,
317
+ leafGeometricErrorCache,
318
+ stack,
306
319
  );
320
+ leafGeometricError =
321
+ leafGeometricError === null
322
+ ? childLeafGeometricError
323
+ : Math.min(leafGeometricError, childLeafGeometricError);
307
324
  });
308
325
  }
309
326
 
310
327
  getLocalExternalTilesetPaths(tile, baseDir).forEach((childTilesetPath) => {
311
- maxDistance = Math.max(
312
- maxDistance,
313
- getTilesetRootLeafDistance(
314
- childTilesetPath,
315
- rootDir,
316
- leafDistanceCache,
317
- stack,
318
- ) + 1,
328
+ const childLeafGeometricError = getTilesetRootLeafGeometricError(
329
+ childTilesetPath,
330
+ rootDir,
331
+ leafGeometricErrorCache,
332
+ stack,
319
333
  );
334
+ leafGeometricError =
335
+ leafGeometricError === null
336
+ ? childLeafGeometricError
337
+ : Math.min(leafGeometricError, childLeafGeometricError);
320
338
  });
321
339
 
322
- return maxDistance;
340
+ return leafGeometricError === null ? ownGeometricError : leafGeometricError;
323
341
  }
324
342
 
325
343
  function scaleTilesetGeometricErrors(
326
344
  tile,
327
345
  geometricErrorScale,
328
346
  geometricErrorLayerScale,
329
- baseDir,
330
- rootDir,
331
- leafDistanceCache,
347
+ leafGeometricError,
332
348
  pathLabel = 'tileset.root',
333
349
  ) {
334
350
  if (!tile || typeof tile !== 'object') {
@@ -338,12 +354,9 @@ function scaleTilesetGeometricErrors(
338
354
  scaleGeometricErrorValue(
339
355
  tile,
340
356
  'geometricError',
341
- getGeometricErrorScaleForLeafDistance(
342
- geometricErrorScale,
343
- geometricErrorLayerScale,
344
- getTileLeafDistance(tile, baseDir, rootDir, leafDistanceCache, new Set()),
345
- pathLabel,
346
- ),
357
+ geometricErrorScale,
358
+ geometricErrorLayerScale,
359
+ leafGeometricError,
347
360
  `${pathLabel}.geometricError`,
348
361
  );
349
362
 
@@ -356,9 +369,7 @@ function scaleTilesetGeometricErrors(
356
369
  child,
357
370
  geometricErrorScale,
358
371
  geometricErrorLayerScale,
359
- baseDir,
360
- rootDir,
361
- leafDistanceCache,
372
+ leafGeometricError,
362
373
  `${pathLabel}.children[${index}]`,
363
374
  );
364
375
  });
@@ -406,7 +417,8 @@ function updateTilesetJsonFile(
406
417
  geometricErrorScale,
407
418
  rootDir,
408
419
  rootTransform = null,
409
- leafDistanceCache = new Map(),
420
+ leafGeometricErrorCache = new Map(),
421
+ globalLeafGeometricError = null,
410
422
  },
411
423
  visited = new Set(),
412
424
  ) {
@@ -434,30 +446,30 @@ function updateTilesetJsonFile(
434
446
  }
435
447
 
436
448
  const tilesetDir = path.dirname(resolvedPath);
449
+ const effectiveLeafGeometricError =
450
+ globalLeafGeometricError == null
451
+ ? getTileLeafGeometricError(
452
+ tileset.root,
453
+ tilesetDir,
454
+ rootDir,
455
+ leafGeometricErrorCache,
456
+ new Set(),
457
+ )
458
+ : globalLeafGeometricError;
459
+
437
460
  scaleGeometricErrorValue(
438
461
  tileset,
439
462
  'geometricError',
440
- getGeometricErrorScaleForLeafDistance(
441
- geometricErrorScale,
442
- geometricErrorLayerScale,
443
- getTileLeafDistance(
444
- tileset.root,
445
- tilesetDir,
446
- rootDir,
447
- leafDistanceCache,
448
- new Set(),
449
- ),
450
- resolvedPath,
451
- ),
463
+ geometricErrorScale,
464
+ geometricErrorLayerScale,
465
+ effectiveLeafGeometricError,
452
466
  `${resolvedPath}.geometricError`,
453
467
  );
454
468
  scaleTilesetGeometricErrors(
455
469
  tileset.root,
456
470
  geometricErrorScale,
457
471
  geometricErrorLayerScale,
458
- tilesetDir,
459
- rootDir,
460
- leafDistanceCache,
472
+ effectiveLeafGeometricError,
461
473
  `${resolvedPath}.root`,
462
474
  );
463
475
  writeJsonAtomic(resolvedPath, tileset);
@@ -470,7 +482,8 @@ function updateTilesetJsonFile(
470
482
  {
471
483
  geometricErrorLayerScale,
472
484
  geometricErrorScale,
473
- leafDistanceCache,
485
+ leafGeometricErrorCache,
486
+ globalLeafGeometricError: effectiveLeafGeometricError,
474
487
  rootDir,
475
488
  },
476
489
  visited,
@@ -936,8 +949,8 @@ function buildViewerHtml(viewerConfig) {
936
949
  .toolbar {
937
950
  display: grid;
938
951
  align-content: start;
939
- gap: 10px;
940
- padding: 14px;
952
+ gap: 8px;
953
+ padding: 10px 14px;
941
954
  border: 1px solid rgba(22, 50, 79, 0.12);
942
955
  border-top: 0;
943
956
  border-radius: 0 0 20px 20px;
@@ -1102,7 +1115,7 @@ function buildViewerHtml(viewerConfig) {
1102
1115
 
1103
1116
  .range-field {
1104
1117
  display: grid;
1105
- gap: 8px;
1118
+ gap: 4px;
1106
1119
  min-width: 0;
1107
1120
  }
1108
1121
 
@@ -1316,9 +1329,9 @@ function buildViewerHtml(viewerConfig) {
1316
1329
  <input
1317
1330
  id="geometric-error-layer-scale"
1318
1331
  type="range"
1319
- min="-0.5849625007211562"
1320
- max="0.5849625007211562"
1321
- step="any"
1332
+ min="-3"
1333
+ max="3"
1334
+ step="0.1"
1322
1335
  value="0"
1323
1336
  />
1324
1337
  </label>