fix(site-map): Map 3 Progress tab Show in 3D flew to a blank spot
The section's height was passed as 0, so the camera target sat far below the map. Use the design surface height, and make the camera fly-to fall back to the surface height when given a wrong one. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
36da7f9f20
commit
2933251b2e
2 changed files with 5 additions and 2 deletions
|
|
@ -4,6 +4,7 @@ import * as React from "react";
|
|||
import type { SiteModelData } from "@/lib/site-map-v2/model-types";
|
||||
import type { ProgressState } from "@/lib/site-map-v2/progress";
|
||||
import { layerCatalog, layerTotals, sectionSummary } from "@/lib/site-map-v3/layer-progress";
|
||||
import { decodeGrid, sampleGrid } from "@/lib/site-map-v3/grid";
|
||||
import type { Selection } from "../scene/types";
|
||||
|
||||
const css = (n: number) => `#${n.toString(16).padStart(6, "0")}`;
|
||||
|
|
@ -13,6 +14,7 @@ export function BuildProgressPanel({ model, state, selected, setSelected, select
|
|||
select(sel: Selection): void; focus(e: number, n: number, z: number, dist: number): void; onOpen(sectionKey: string): void; canEdit: boolean;
|
||||
}) {
|
||||
const catalog = React.useMemo(() => layerCatalog(model), [model]);
|
||||
const design = React.useMemo(() => decodeGrid(model.surface), [model.surface]);
|
||||
const rows = model.road.sections.map(s => ({ s, sum: sectionSummary(model, state, s.key, selected) })).filter(r => r.sum.layersTotal > 0);
|
||||
const full = rows.filter(r => r.sum.layersDone === r.sum.layersTotal).length, none = rows.filter(r => r.sum.fraction === 0).length;
|
||||
const toggle = (id: string) => { const n = new Set(selected); if (n.has(id)) n.delete(id); else n.add(id); setSelected(n); };
|
||||
|
|
@ -41,7 +43,7 @@ export function BuildProgressPanel({ model, state, selected, setSelected, select
|
|||
<button type="button" className="min-w-0 flex-1 text-left" onClick={() => select({ type: "section", section: s.key })}>
|
||||
<b className="block truncate">{s.name} {s.from}–{Math.round(s.to)} m</b>
|
||||
<span className="mt-1 flex items-center gap-1" aria-label={`${sum.layersDone} of ${sum.layersTotal} layers done`}>{sum.layers.map(l => <i key={l.id} title={l.name} className="h-3 w-3 rounded-sm border" style={{ background: l.done >= 0.999 ? "#22c55e" : l.done > 0 ? "#f59e0b" : "transparent" }} />)}<span className="ml-1 text-xs tabular-nums text-muted-foreground">{sum.layersDone}/{sum.layersTotal}</span></span></button>
|
||||
{c && <button type="button" className="min-h-9 rounded-md border px-2 text-xs hover:bg-muted" onClick={() => { select({ type: "section", section: s.key }); focus(c[0], c[1], 0, 60); }}>Show in 3D</button>}
|
||||
{c && <button type="button" className="min-h-9 rounded-md border px-2 text-xs hover:bg-muted" onClick={() => { select({ type: "section", section: s.key }); focus(c[0], c[1], sampleGrid(design, c[0], c[1]) ?? model.surface.zmin, 60); }}>Show in 3D</button>}
|
||||
<button type="button" disabled={!canEdit} className="min-h-9 rounded-md border px-2 text-xs hover:bg-muted disabled:opacity-50" onClick={() => { select({ type: "section", section: s.key }); onOpen(s.key); }}>Tick layers</button>
|
||||
</li>; })}</ul></section>}
|
||||
{!rows.length && <p className="text-muted-foreground">Tick at least one layer above to see the sections.</p>}
|
||||
|
|
|
|||
|
|
@ -142,7 +142,8 @@ export function createSiteMap(container: HTMLElement, model: SiteModelData, stat
|
|||
}
|
||||
/** Fly to a spot, tilted so it reads in 3D, and mark it with a beacon for a few seconds. */
|
||||
function focus(e: number, n: number, z: number, dist: number) {
|
||||
const t = ctx.W(e, n, z), off = camera.position.clone().sub(controls.target); off.y = 0;
|
||||
const zz = Number.isFinite(z) && Math.abs(z - zRef) < 200 ? z : ctx.designZ(e, n); // a wrong height would fly the camera off the map
|
||||
const t = ctx.W(e, n, zz), off = camera.position.clone().sub(controls.target); off.y = 0;
|
||||
if (off.lengthSq() < 1) off.set(-0.3, 0, 0.8);
|
||||
off.normalize().multiplyScalar(dist * 0.62); off.y = dist * 0.78;
|
||||
const p0 = camera.position.clone(), t0 = controls.target.clone(), p1 = t.clone().add(off);
|
||||
|
|
|
|||
Loading…
Reference in a new issue