File size: 2,460 Bytes
970fc3e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import { readdir, readFile } from "node:fs/promises";
import { join } from "node:path";
import { scanContentAnchors } from "../shared/scan-structure.mjs";
import { validateContentAnchors } from "../shared/scan-furnishing.mjs";
async function resolveScanBlueprint(scene, sceneFolder) {
  if (scene.scanReconstruction?.blueprint) return structuredClone(scene.scanReconstruction.blueprint);
  let files;
  try {
    files = await readdir(join(sceneFolder, "scan-previews"));
  } catch (error) {
    if (error.code !== "ENOENT") throw error;
    files = [];
  }
  for (const file of files.filter((f) => /^[a-f\d-]+\.json$/i.test(f)).sort()) {
    const saved = JSON.parse(await readFile(join(sceneFolder, "scan-previews", file), "utf8"));
    if (matchesScanGeometry(scene, saved.scene) && saved.survey?.planes && saved.alignment) return { planes: saved.survey.planes, alignment: saved.alignment, referenceFloor: saved.scene.objects.find((o) => o.id === "ground") };
  }
  throw new Error("Original scan for this scene was not found. Preview and apply the scan structure first.");
}
function matchesScanGeometry(scene, saved) {
  if (!saved?.objects?.length) return false;
  const current = new Map(scene.objects.map((o) => [o.id, o]));
  return saved.objects.every((a) => {
    const b = current.get(a.id);
    return b && JSON.stringify([a.shape, a.position, a.size, a.rotation]) === JSON.stringify([b.shape, b.position, b.size, b.rotation]);
  });
}
async function resolveScanContent(scene, sceneFolder) {
  if (!scene.scanStructure) throw new Error("Apply the scan structure before adding scanned objects");
  if (scene.scanStructure.contentAnchors) return validateContentAnchors(scene.scanStructure.contentAnchors);
  let files;
  try {
    files = await readdir(join(sceneFolder, "scan-previews"));
  } catch (error) {
    if (error.code !== "ENOENT") throw error;
    files = [];
  }
  for (const file of files.filter((f) => /^[a-f\d-]+\.json$/i.test(f)).sort()) {
    const saved = JSON.parse(await readFile(join(sceneFolder, "scan-previews", file), "utf8"));
    if (matchesScanGeometry(scene, saved.scene) && saved.survey?.planes && saved.alignment) return validateContentAnchors(scanContentAnchors(saved.survey.planes, saved.alignment, scene));
  }
  throw new Error("Matching original scan was not found. Current scene is preserved. Preview the scan structure again.");
}
export {
  matchesScanGeometry,
  resolveScanBlueprint,
  resolveScanContent
};