(bounds, rawExtents, options = {}, labelScaleFactor = 1)
| 540 | } |
| 541 | |
| 542 | updateGridLabels(bounds, rawExtents, options = {}, labelScaleFactor = 1) { |
| 543 | this.clearGridLabels(); |
| 544 | if (!bounds || !Number.isFinite(bounds.min.x) || !Number.isFinite(bounds.max.x)) { |
| 545 | return; |
| 546 | } |
| 547 | if (labelScaleFactor === 0) { |
| 548 | return; |
| 549 | } |
| 550 | |
| 551 | const labelScale = Math.max(labelScaleFactor, 0.01); |
| 552 | const labelOffset = Math.max(0.2, labelScale * 0.4); |
| 553 | const baseY = (this.gridBaseY ?? bounds.min.y) + 0.06; |
| 554 | |
| 555 | const eastMin = rawExtents?.east?.min ?? bounds.min.x; |
| 556 | const eastMax = rawExtents?.east?.max ?? bounds.max.x; |
| 557 | const northMin = rawExtents?.north?.min ?? -bounds.max.z; |
| 558 | const northMax = rawExtents?.north?.max ?? -bounds.min.z; |
| 559 | |
| 560 | const spacing = Math.max(this.appliedGridStep || this.gridSpacing, 0.0001); |
| 561 | const maxLabels = 200; |
| 562 | const computeStep = (range) => { |
| 563 | if (!Number.isFinite(range) || range <= 0) return spacing; |
| 564 | let step = spacing; |
| 565 | while (range / step > maxLabels) { |
| 566 | step *= 2; |
| 567 | } |
| 568 | return step; |
| 569 | }; |
| 570 | |
| 571 | const formatValue = (value, step) => { |
| 572 | if (!Number.isFinite(value)) return "0"; |
| 573 | const absStep = Math.max(Math.abs(step), spacing); |
| 574 | if (absStep >= 500) return Math.round(value).toString(); |
| 575 | if (absStep >= 100) return value.toFixed(0); |
| 576 | if (absStep >= 10) return value.toFixed(1); |
| 577 | if (absStep >= 1) return value.toFixed(2); |
| 578 | return value.toFixed(3); |
| 579 | }; |
| 580 | |
| 581 | const eastStep = computeStep(eastMax - eastMin); |
| 582 | const northStep = computeStep(northMax - northMin); |
| 583 | |
| 584 | const labelFrontZ = bounds.max.z + labelOffset; |
| 585 | const labelBackX = bounds.min.x - labelOffset; |
| 586 | |
| 587 | const toWorldX = (rawEast) => (options.flipEast ? -rawEast : rawEast); |
| 588 | const toWorldZ = (rawNorth) => (options.flipNorth ? rawNorth : -rawNorth); |
| 589 | |
| 590 | const eastStart = Math.floor(eastMin / eastStep) * eastStep; |
| 591 | const eastEnd = Math.ceil(eastMax / eastStep) * eastStep; |
| 592 | const eastSteps = Math.max(0, Math.ceil((eastEnd - eastStart) / eastStep)); |
| 593 | for (let i = 0; i <= eastSteps; i += 1) { |
| 594 | const value = eastStart + i * eastStep; |
| 595 | if (value < eastMin - 1e-6 || value > eastMax + 1e-6) continue; |
| 596 | const worldX = toWorldX(value); |
| 597 | const formatted = formatValue(value, eastStep); |
| 598 | const sprite = this.createTextSprite(`${value >= 0 ? "+" : ""}${formatted}`); |
| 599 | sprite.scale.multiplyScalar(labelScale); |
no test coverage detected