floor-editor-ts 1.0.7 → 1.0.9

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.
@@ -60868,19 +60868,6 @@ function LayersPanel($$anchor, $$props) {
60868
60868
  delegate(["click", "keydown"]);
60869
60869
  //#endregion
60870
60870
  //#region src/lib/utils/furnitureIcons.ts
60871
- /**
60872
- * Architectural top-down furniture renderers for 2D canvas.
60873
- * Each function draws within a normalized rect: (-w/2, -d/2) to (w/2, d/2)
60874
- * where w = width*zoom, d = depth*zoom. Context is already translated & rotated.
60875
- */
60876
- function getHeatColor(value) {
60877
- switch (value) {
60878
- case 1: return "rgba(255, 220, 0, 0.25)";
60879
- case 2: return "rgba(255, 140, 0, 0.4)";
60880
- case 3: return "rgba(255, 60, 0, 0.6)";
60881
- default: return "rgba(0,0,0,0)";
60882
- }
60883
- }
60884
60871
  function roundRect(ctx, x, y, w, h, r) {
60885
60872
  r = Math.min(r, w / 2, h / 2);
60886
60873
  ctx.beginPath();
@@ -61688,103 +61675,122 @@ var drawSymGasLine = (ctx, w, d, color) => {
61688
61675
  ctx.fillText("G", 0, 0);
61689
61676
  };
61690
61677
  var persons = [];
61691
- var personGlow = null;
61692
61678
  var lastSpawnTime = 0;
61693
61679
  var SPAWN_INTERVAL = 1e3;
61694
61680
  var MAX_PERSONS = 20;
61695
- var drawCamera = (ctx, w, d, color, heatmapMatrix, hasPerson) => {
61681
+ var getHeatmapColor = (t, alpha = 1) => {
61682
+ t = Math.max(0, Math.min(t, 1));
61683
+ let r, g, b;
61684
+ if (t < .35) {
61685
+ const k = t / .35;
61686
+ r = 0;
61687
+ g = Math.round(120 + 135 * k);
61688
+ b = Math.round(255 - 180 * k);
61689
+ } else if (t < .7) {
61690
+ const k = (t - .35) / .35;
61691
+ r = Math.round(255 * k);
61692
+ g = 255;
61693
+ b = 0;
61694
+ } else {
61695
+ const k = (t - .7) / .3;
61696
+ r = 255;
61697
+ g = Math.round(255 - 255 * k);
61698
+ b = 0;
61699
+ }
61700
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
61701
+ };
61702
+ var drawCamera = (ctx, w, d, color, heatmapMatrix, hasPerson = false, showHeatmap = false) => {
61696
61703
  const bodyRadius = 4;
61697
61704
  const lensR = Math.min(w, d) * .25;
61698
61705
  const range = Math.max(w, d) * 6;
61699
61706
  const fov = Math.PI / 2;
61700
- ctx.save();
61701
- const gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, range);
61702
- gradient.addColorStop(0, color + "66");
61703
- gradient.addColorStop(.5, color + "33");
61704
- gradient.addColorStop(1, color + "00");
61705
- ctx.fillStyle = gradient;
61706
- ctx.beginPath();
61707
- ctx.moveTo(0, 0);
61708
- ctx.arc(0, 0, range, -fov / 2, fov / 2);
61709
- ctx.closePath();
61710
- ctx.globalCompositeOperation = "lighter";
61711
- ctx.fill();
61712
- ctx.restore();
61713
- if (heatmapMatrix) {
61714
- const rows = heatmapMatrix.length;
61715
- const cols = heatmapMatrix[0].length;
61716
- const cellSize = Math.max(w, d) * .3;
61707
+ if (showHeatmap) {
61708
+ var _heatmapMatrix$;
61717
61709
  ctx.save();
61718
- ctx.translate(0, 0);
61710
+ const coneGradient = ctx.createRadialGradient(0, 0, 0, 0, 0, range);
61711
+ coneGradient.addColorStop(0, color + "55");
61712
+ coneGradient.addColorStop(.45, color + "22");
61713
+ coneGradient.addColorStop(1, color + "00");
61714
+ ctx.fillStyle = coneGradient;
61719
61715
  ctx.globalCompositeOperation = "lighter";
61720
- ctx.filter = "blur(8px)";
61721
- const paths = {
61722
- 1: new Path2D(),
61723
- 2: new Path2D(),
61724
- 3: new Path2D(),
61725
- 4: new Path2D()
61726
- };
61727
- for (let y = 0; y < rows; y++) for (let x = 0; x < cols; x++) {
61728
- const value = heatmapMatrix[y][x];
61729
- if (value === 0) continue;
61730
- const angle = -fov / 2 + x / (cols - 1) * fov;
61731
- const r = y / rows * range;
61732
- const px = Math.cos(angle) * r;
61733
- const py = Math.sin(angle) * r;
61734
- paths[value].moveTo(px, py);
61735
- paths[value].arc(px, py, cellSize * .4, 0, Math.PI * 2);
61736
- }
61737
- Object.keys(paths).forEach((v) => {
61738
- ctx.fillStyle = getHeatColor(Number(v));
61739
- ctx.fill(paths[v]);
61740
- });
61716
+ ctx.beginPath();
61717
+ ctx.moveTo(0, 0);
61718
+ ctx.arc(0, 0, range, -fov / 2, fov / 2);
61719
+ ctx.closePath();
61720
+ ctx.fill();
61741
61721
  ctx.restore();
61742
- }
61743
- {
61744
- const now = Date.now();
61745
- const range = Math.max(w, d) * 6;
61746
- const fov = Math.PI / 2;
61747
- if (persons.length < MAX_PERSONS && now - lastSpawnTime > SPAWN_INTERVAL) {
61748
- lastSpawnTime = now;
61749
- persons.push({
61750
- startTime: now,
61751
- duration: 2e3 + Math.random() * 1e3,
61752
- direction: Math.random() > .5 ? "far-to-near" : "near-to-far",
61753
- angle: (Math.random() - .5) * fov * .8
61754
- });
61722
+ if ((heatmapMatrix === null || heatmapMatrix === void 0 ? void 0 : heatmapMatrix.length) && ((_heatmapMatrix$ = heatmapMatrix[0]) === null || _heatmapMatrix$ === void 0 ? void 0 : _heatmapMatrix$.length)) {
61723
+ const rows = heatmapMatrix.length;
61724
+ const cols = heatmapMatrix[0].length;
61725
+ const maxValue = Math.max(...heatmapMatrix.flat());
61726
+ if (maxValue > 0) {
61727
+ ctx.save();
61728
+ ctx.globalCompositeOperation = "lighter";
61729
+ ctx.filter = "blur(10px)";
61730
+ const radius = range / rows * 1.8;
61731
+ for (let y = 0; y < rows; y++) for (let x = 0; x < cols; x++) {
61732
+ const value = heatmapMatrix[y][x];
61733
+ if (!value || value <= 0) continue;
61734
+ const intensity = Math.min(value / maxValue, 1);
61735
+ const angle = -fov / 2 + (cols === 1 ? .5 : x / (cols - 1)) * fov;
61736
+ const r = (y + .5) / rows * range;
61737
+ const px = Math.cos(angle) * r;
61738
+ const py = Math.sin(angle) * r;
61739
+ const gradient = ctx.createRadialGradient(px, py, 0, px, py, radius);
61740
+ const alpha = .12 + intensity * .75;
61741
+ gradient.addColorStop(0, getHeatmapColor(intensity, alpha));
61742
+ gradient.addColorStop(.45, getHeatmapColor(intensity, alpha * .45));
61743
+ gradient.addColorStop(1, getHeatmapColor(intensity, 0));
61744
+ ctx.fillStyle = gradient;
61745
+ ctx.beginPath();
61746
+ ctx.arc(px, py, radius, 0, Math.PI * 2);
61747
+ ctx.fill();
61748
+ }
61749
+ ctx.restore();
61750
+ }
61755
61751
  }
61756
- persons = persons.filter((p) => {
61757
- let t = (now - p.startTime) / p.duration;
61758
- if (t >= 1) return false;
61759
- t = Math.max(0, Math.min(t, 1));
61760
- let r;
61761
- if (p.direction === "far-to-near") r = range * (.9 - t * .8);
61762
- else r = range * (.1 + t * .8);
61763
- const x = Math.cos(p.angle) * r;
61764
- const y = Math.sin(p.angle) * r;
61765
- ctx.save();
61766
- ctx.translate(x, y);
61767
- ctx.globalCompositeOperation = "lighter";
61768
- const scale = .5 + (1 - r / range);
61769
- ctx.scale(scale, scale);
61770
- ctx.globalAlpha = 1 - t;
61771
- if (!personGlow) {
61772
- personGlow = ctx.createRadialGradient(0, 0, 0, 0, 0, 20);
61773
- personGlow.addColorStop(0, "rgba(255,0,0,0.8)");
61774
- personGlow.addColorStop(1, "rgba(255,0,0,0)");
61752
+ if (hasPerson) {
61753
+ const now = Date.now();
61754
+ if (persons.length < MAX_PERSONS && now - lastSpawnTime > SPAWN_INTERVAL) {
61755
+ lastSpawnTime = now;
61756
+ persons.push({
61757
+ startTime: now,
61758
+ duration: 2e3 + Math.random() * 1e3,
61759
+ direction: Math.random() > .5 ? "far-to-near" : "near-to-far",
61760
+ angle: (Math.random() - .5) * fov * .8
61761
+ });
61775
61762
  }
61776
- ctx.fillStyle = personGlow;
61777
- ctx.beginPath();
61778
- ctx.arc(0, 0, 20, 0, Math.PI * 2);
61779
- ctx.fill();
61780
- ctx.beginPath();
61781
- ctx.arc(0, 0, 6, 0, Math.PI * 2);
61782
- ctx.fillStyle = "red";
61783
- ctx.fill();
61784
- ctx.restore();
61785
- return true;
61786
- });
61787
- }
61763
+ persons = persons.filter((p) => {
61764
+ let t = (now - p.startTime) / p.duration;
61765
+ if (t >= 1) return false;
61766
+ t = Math.max(0, Math.min(t, 1));
61767
+ let r;
61768
+ if (p.direction === "far-to-near") r = range * (.9 - t * .8);
61769
+ else r = range * (.1 + t * .8);
61770
+ const x = Math.cos(p.angle) * r;
61771
+ const y = Math.sin(p.angle) * r;
61772
+ ctx.save();
61773
+ ctx.translate(x, y);
61774
+ ctx.globalCompositeOperation = "lighter";
61775
+ const scale = .5 + (1 - r / range);
61776
+ ctx.scale(scale, scale);
61777
+ ctx.globalAlpha = 1 - t;
61778
+ const glow = ctx.createRadialGradient(0, 0, 0, 0, 0, 20);
61779
+ glow.addColorStop(0, "rgba(255,0,0,0.8)");
61780
+ glow.addColorStop(1, "rgba(255,0,0,0)");
61781
+ ctx.fillStyle = glow;
61782
+ ctx.beginPath();
61783
+ ctx.arc(0, 0, 20, 0, Math.PI * 2);
61784
+ ctx.fill();
61785
+ ctx.beginPath();
61786
+ ctx.arc(0, 0, 6, 0, Math.PI * 2);
61787
+ ctx.fillStyle = "red";
61788
+ ctx.fill();
61789
+ ctx.restore();
61790
+ return true;
61791
+ });
61792
+ } else persons = [];
61793
+ } else persons = [];
61788
61794
  ctx.fillStyle = color + "40";
61789
61795
  ctx.strokeStyle = color;
61790
61796
  ctx.lineWidth = 1;
@@ -61879,12 +61885,12 @@ var iconDrawers = {
61879
61885
  * @param w - pixel width (catalogWidth * zoom)
61880
61886
  * @param d - pixel depth (catalogDepth * zoom)
61881
61887
  */
61882
- function drawFurnitureIcon(ctx, catalogId, w, d, color, strokeColor, heatmapMatrix, hasPerson = false) {
61888
+ function drawFurnitureIcon(ctx, catalogId, w, d, color, strokeColor, heatmapMatrix, hasPerson = false, showHeatmap = false) {
61883
61889
  ctx.fillStyle = color + "60";
61884
61890
  ctx.strokeStyle = strokeColor;
61885
61891
  ctx.lineWidth = 1;
61886
61892
  const drawer = iconDrawers[catalogId];
61887
- if (drawer) drawer(ctx, w, d, color, heatmapMatrix, hasPerson);
61893
+ if (drawer) drawer(ctx, w, d, color, heatmapMatrix, hasPerson, showHeatmap);
61888
61894
  else {
61889
61895
  roundRect(ctx, -w / 2, -d / 2, w, d, 2);
61890
61896
  ctx.fill();
@@ -63276,7 +63282,7 @@ function drawFurnitureItem(cs, item, selected) {
63276
63282
  const itemColor = (_item$color = item.color) !== null && _item$color !== void 0 ? _item$color : cat.color;
63277
63283
  const strokeColor = selected ? "#3b82f6" : itemColor;
63278
63284
  ctx.lineWidth = selected ? 2 : 1;
63279
- drawFurnitureIcon(ctx, item.catalogId, w, d, itemColor, strokeColor, item.heatmapMatrix);
63285
+ drawFurnitureIcon(ctx, item.catalogId, w, d, itemColor, strokeColor, item.heatmapMatrix, item.hasPerson, item.showHeatmap);
63280
63286
  const fontSize = Math.max(8, Math.min(12, Math.min(w, d) * .2));
63281
63287
  if (Math.min(w, d) > 20) {
63282
63288
  ctx.fillStyle = "#374151";
@@ -64364,13 +64370,14 @@ var root_12 = /* @__PURE__ */ from_html(`<div class="absolute bottom-12 right-2
64364
64370
  var root_16 = /* @__PURE__ */ from_html(`<button class="w-7 h-7 flex items-center justify-center rounded hover:bg-gray-100 text-gray-500 hover:text-gray-700" title="Flip swing" aria-label="Flip swing"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M7 16V4m0 0L3 8m4-4l4 4M17 8v12m0 0l4-4m-4 4l-4-4"></path></svg></button>`);
64365
64371
  var root_17 = /* @__PURE__ */ from_html(`<button class="w-7 h-7 flex items-center justify-center rounded hover:bg-gray-100 text-gray-500 hover:text-gray-700" title="Split wall at midpoint" aria-label="Split wall at midpoint"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2v20M4 12h4M16 12h4"></path></svg></button>`);
64366
64372
  var root_15 = /* @__PURE__ */ from_html(`<div class="absolute z-40 flex items-center gap-0.5 bg-white rounded-lg shadow-lg border border-gray-200 px-1 py-0.5"><button class="w-7 h-7 flex items-center justify-center rounded hover:bg-gray-100 text-gray-500 hover:text-gray-700" title="Duplicate" aria-label="Duplicate"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"></rect><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"></path></svg></button> <!> <!> <div class="w-px h-5 bg-gray-200 mx-0.5"></div> <button class="w-7 h-7 flex items-center justify-center rounded hover:bg-red-50 text-gray-400 hover:text-red-600" title="Delete" aria-label="Delete"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2m3 0v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6h14"></path></svg></button></div>`);
64367
- var root_18 = /* @__PURE__ */ from_html(`<div class="absolute top-2 left-1/2 -translate-x-1/2 bg-blue-600 text-white px-3 py-1 rounded-full text-xs shadow">Click to add wall segment · Double-click to finish · C to close loop · Esc to cancel</div>`);
64373
+ var root_18 = /* @__PURE__ */ from_html(`<div class="absolute top-2 left-1/2 -translate-x-1/2 bg-blue-600 text-white px-3 py-1 rounded-full text-xs shadow">Click to add wall segment · Double-click to finish · C to close loop ·
64374
+ Esc to cancel</div>`);
64368
64375
  var root_19 = /* @__PURE__ */ from_html(`<div class="absolute top-2 left-1/2 -translate-x-1/2 bg-purple-600 text-white px-3 py-1 rounded-full text-xs shadow"> </div>`);
64369
64376
  var root_20 = /* @__PURE__ */ from_html(`<div class="absolute top-2 left-1/2 -translate-x-1/2 bg-red-600 text-white px-3 py-1 rounded-full text-xs shadow">Right-click two points to measure · M to exit · Esc to cancel</div>`);
64370
64377
  var root_21 = /* @__PURE__ */ from_html(`<div class="absolute top-2 left-1/2 -translate-x-1/2 bg-emerald-600 text-white px-3 py-1 rounded-full text-xs shadow">Click to place text label · Esc to cancel</div>`);
64371
64378
  var root_22 = /* @__PURE__ */ from_html(`<div class="absolute top-2 left-1/2 -translate-x-1/2 bg-indigo-600 text-white px-3 py-1 rounded-full text-xs shadow"> </div>`);
64372
64379
  var root_1$5 = /* @__PURE__ */ from_html(`<!> <!> <!> <!> <div class="absolute bottom-2 right-2 bg-white/80 rounded px-2 py-1 text-xs text-gray-500 flex gap-3"><!> <!> <!> <span> </span> <button class="hover:text-gray-700" title="Zoom to Fit (F)">⊞ Fit</button> <button class="hover:text-gray-700" title="Toggle Grid (G)"> </button> <button class="hover:text-gray-700" title="Toggle Snap to Grid (S)"> </button> <button class="hover:text-gray-700" title="Toggle Furniture"> </button> <button class="hover:text-gray-700" title="Layer Visibility">🗂 Layers</button> <button class="hover:text-gray-700" title="Toggle Rulers"> </button> <button class="hover:text-gray-700" title="Toggle Mini-map"> </button></div> <!> <!> <!> <!> <!> <!> <!> <div class="absolute bottom-3 left-3 z-20 flex items-center gap-1 bg-white rounded-lg shadow-lg border border-gray-200 px-1 py-0.5"><button class="w-7 h-7 flex items-center justify-center rounded hover:bg-gray-100 text-gray-600 hover:text-gray-800 font-bold text-lg" title="Zoom Out (−)" aria-label="Zoom out">−</button> <button class="min-w-[3.5rem] h-7 flex items-center justify-center rounded hover:bg-gray-100 text-xs font-medium text-gray-600 hover:text-gray-800 tabular-nums" title="Reset to 100%" aria-label="Zoom to 100%"> </button> <button class="w-7 h-7 flex items-center justify-center rounded hover:bg-gray-100 text-gray-600 hover:text-gray-800 font-bold text-lg" title="Zoom In (+)" aria-label="Zoom in">+</button> <div class="w-px h-5 bg-gray-200"></div> <button class="w-7 h-7 flex items-center justify-center rounded hover:bg-gray-100 text-gray-500 hover:text-gray-700 text-sm" title="Zoom to Fit (F)" aria-label="Zoom to fit">⊞</button></div> <!>`, 1);
64373
- var root = /* @__PURE__ */ from_html(`<div class="w-full h-full relative overflow-hidden" role="application"><canvas aria-label="Floor plan editor canvas"></canvas> <!></div>`);
64380
+ var root = /* @__PURE__ */ from_html(`<div class="w-full h-full relative overflow-hidden" role="application"><div><canvas aria-label="Floor plan editor canvas"></canvas></div> <!></div>`);
64374
64381
  function FloorPlanCanvas($$anchor, $$props) {
64375
64382
  push($$props, true);
64376
64383
  const $panMode = () => store_get(panMode, "$panMode", $$stores);
@@ -64383,22 +64390,7 @@ function FloorPlanCanvas($$anchor, $$props) {
64383
64390
  let camX = /* @__PURE__ */ state(0);
64384
64391
  let camY = /* @__PURE__ */ state(0);
64385
64392
  let zoom = /* @__PURE__ */ state(1);
64386
- function createRandomMatrix(size = 20, clusterCount = 1) {
64387
- const matrix = Array.from({ length: size }, () => Array(size).fill(0));
64388
- for (let c = 0; c < clusterCount; c++) {
64389
- const cx = Math.random() * size;
64390
- const cy = Math.random() * size;
64391
- const sigma = size * .15;
64392
- for (let y = 0; y < size; y++) for (let x = 0; x < size; x++) {
64393
- const dx = x - cx;
64394
- const dy = y - cy;
64395
- const value = Math.exp(-(dx * dx + dy * dy) / (2 * sigma * sigma));
64396
- const level = Math.floor(value * 4);
64397
- matrix[y][x] = Math.max(matrix[y][x], level);
64398
- }
64399
- }
64400
- return matrix;
64401
- }
64393
+ let needsFitToCanvas = true;
64402
64394
  let canvasDirty = true;
64403
64395
  function markDirty() {
64404
64396
  canvasDirty = true;
@@ -64519,7 +64511,6 @@ function FloorPlanCanvas($$anchor, $$props) {
64519
64511
  const RULER_SIZE = 24;
64520
64512
  let detectedRooms = /* @__PURE__ */ state(proxy([]));
64521
64513
  let lastWallHash = "";
64522
- const GRID = 20;
64523
64514
  const SNAP = 10;
64524
64515
  const MAGNETIC_SNAP = 15;
64525
64516
  const WALL_SNAP_DIST = 30;
@@ -64821,49 +64812,7 @@ function FloorPlanCanvas($$anchor, $$props) {
64821
64812
  canvas.height = get(height);
64822
64813
  }
64823
64814
  markDirty();
64824
- if ($$props.viewOnly) requestAnimationFrame(() => {
64825
- zoomToFit();
64826
- });
64827
- }
64828
- function drawGrid() {
64829
- if (!ctx || !get(showGrid)) return;
64830
- const step = (get(currentSnapToGrid) ? get(currentGridSize) : GRID) * get(zoom);
64831
- if (step < 4) return;
64832
- ctx.strokeStyle = "#e8eaed";
64833
- ctx.lineWidth = .5;
64834
- const offX = (get(width) / 2 - get(camX) * get(zoom)) % step;
64835
- const offY = (get(height) / 2 - get(camY) * get(zoom)) % step;
64836
- for (let x = offX; x < get(width); x += step) {
64837
- ctx.beginPath();
64838
- ctx.moveTo(x, 0);
64839
- ctx.lineTo(x, get(height));
64840
- ctx.stroke();
64841
- }
64842
- for (let y = offY; y < get(height); y += step) {
64843
- ctx.beginPath();
64844
- ctx.moveTo(0, y);
64845
- ctx.lineTo(get(width), y);
64846
- ctx.stroke();
64847
- }
64848
- const majorStep = 100 * get(zoom);
64849
- if (majorStep >= 20) {
64850
- ctx.strokeStyle = "#d1d5db";
64851
- ctx.lineWidth = .8;
64852
- const mOffX = (get(width) / 2 - get(camX) * get(zoom)) % majorStep;
64853
- const mOffY = (get(height) / 2 - get(camY) * get(zoom)) % majorStep;
64854
- for (let x = mOffX; x < get(width); x += majorStep) {
64855
- ctx.beginPath();
64856
- ctx.moveTo(x, 0);
64857
- ctx.lineTo(x, get(height));
64858
- ctx.stroke();
64859
- }
64860
- for (let y = mOffY; y < get(height); y += majorStep) {
64861
- ctx.beginPath();
64862
- ctx.moveTo(0, y);
64863
- ctx.lineTo(get(width), y);
64864
- ctx.stroke();
64865
- }
64866
- }
64815
+ needsFitToCanvas = true;
64867
64816
  }
64868
64817
  /** Get point on wall at parameter t (0-1), handling curves */
64869
64818
  function wallPointAt(w, t) {
@@ -65249,195 +65198,6 @@ function FloorPlanCanvas($$anchor, $$props) {
65249
65198
  function drawColumn$1(col, selected) {
65250
65199
  drawColumn(getCS(), col, selected);
65251
65200
  }
65252
- function rulerLabel(worldCm, tickStep, isImperial) {
65253
- if (isImperial) {
65254
- const inches = worldCm / 2.54;
65255
- const ft = inches / 12;
65256
- if (tickStep / 2.54 >= 12) return `${ft % 1 === 0 ? ft.toFixed(0) : ft.toFixed(1)}'`;
65257
- return `${Math.round(inches)}"`;
65258
- }
65259
- if (tickStep >= 100) {
65260
- const m = worldCm / 100;
65261
- return `${worldCm % 100 === 0 ? m.toFixed(0) : m.toFixed(1)}m`;
65262
- }
65263
- return `${Math.round(worldCm)}`;
65264
- }
65265
- function drawRulers() {
65266
- if (!ctx || !get(showRulers) || $$props.viewOnly) return;
65267
- const R = RULER_SIZE;
65268
- const fontSize = 9;
65269
- const isImperial = get(dimSettings).units === "imperial";
65270
- ctx.save();
65271
- let tickStep;
65272
- let minorDiv;
65273
- let minorStep;
65274
- if (isImperial) {
65275
- const inchCm = 2.54;
65276
- const niceStepsCm = [
65277
- 1,
65278
- 2,
65279
- 6,
65280
- 12,
65281
- 24,
65282
- 60,
65283
- 120,
65284
- 240,
65285
- 600,
65286
- 1200,
65287
- 2400
65288
- ].map((i) => i * inchCm);
65289
- tickStep = niceStepsCm[niceStepsCm.length - 1];
65290
- for (const s of niceStepsCm) if (s * get(zoom) >= 40) {
65291
- tickStep = s;
65292
- break;
65293
- }
65294
- const tickInches = tickStep / inchCm;
65295
- minorDiv = tickInches >= 12 ? 6 : tickInches >= 6 ? 3 : 2;
65296
- minorStep = tickStep / minorDiv;
65297
- } else {
65298
- const niceSteps = [
65299
- 1,
65300
- 2,
65301
- 5,
65302
- 10,
65303
- 20,
65304
- 50,
65305
- 100,
65306
- 200,
65307
- 500,
65308
- 1e3,
65309
- 2e3,
65310
- 5e3
65311
- ];
65312
- tickStep = niceSteps[niceSteps.length - 1];
65313
- for (const s of niceSteps) if (s * get(zoom) >= 40) {
65314
- tickStep = s;
65315
- break;
65316
- }
65317
- minorDiv = tickStep >= 100 ? 5 : tickStep >= 10 ? 5 : 2;
65318
- minorStep = tickStep / minorDiv;
65319
- }
65320
- ctx.fillStyle = "#f1f3f5";
65321
- ctx.fillRect(R, 0, get(width) - R, R);
65322
- ctx.strokeStyle = "#d1d5db";
65323
- ctx.lineWidth = 1;
65324
- ctx.beginPath();
65325
- ctx.moveTo(R, R);
65326
- ctx.lineTo(get(width), R);
65327
- ctx.stroke();
65328
- const worldLeft = screenToWorld(R, 0).x;
65329
- const worldRight = screenToWorld(get(width), 0).x;
65330
- const startTick = Math.floor(worldLeft / minorStep) * minorStep;
65331
- ctx.fillStyle = "#6b7280";
65332
- ctx.font = `${fontSize}px sans-serif`;
65333
- ctx.textAlign = "center";
65334
- ctx.textBaseline = "top";
65335
- for (let wx = startTick; wx <= worldRight; wx += minorStep) {
65336
- const sx = worldToScreen(wx, 0).x;
65337
- if (sx < R) continue;
65338
- const isMajor = Math.abs(wx % tickStep) < .01;
65339
- const isMid = !isMajor && Math.abs(wx % (tickStep / 2)) < .01 && minorDiv >= 4;
65340
- const tickH = isMajor ? R * .7 : isMid ? R * .45 : R * .25;
65341
- const isOrigin = Math.abs(wx) < .01;
65342
- ctx.strokeStyle = isOrigin ? "#ef4444" : isMajor ? "#9ca3af" : "#d1d5db";
65343
- ctx.lineWidth = isOrigin ? 1.5 : isMajor ? 1 : .5;
65344
- ctx.beginPath();
65345
- ctx.moveTo(sx, R);
65346
- ctx.lineTo(sx, R - tickH);
65347
- ctx.stroke();
65348
- if (isMajor) {
65349
- ctx.fillStyle = isOrigin ? "#ef4444" : "#6b7280";
65350
- const label = isOrigin ? "0" : rulerLabel(wx, tickStep, isImperial);
65351
- ctx.fillText(label, sx, 2);
65352
- ctx.fillStyle = "#6b7280";
65353
- }
65354
- }
65355
- ctx.fillStyle = "#f1f3f5";
65356
- ctx.fillRect(0, R, R, get(height) - R);
65357
- ctx.strokeStyle = "#d1d5db";
65358
- ctx.lineWidth = 1;
65359
- ctx.beginPath();
65360
- ctx.moveTo(R, R);
65361
- ctx.lineTo(R, get(height));
65362
- ctx.stroke();
65363
- const worldTop = screenToWorld(0, R).y;
65364
- const worldBottom = screenToWorld(0, get(height)).y;
65365
- const startTickY = Math.floor(worldTop / minorStep) * minorStep;
65366
- ctx.textAlign = "right";
65367
- ctx.textBaseline = "middle";
65368
- for (let wy = startTickY; wy <= worldBottom; wy += minorStep) {
65369
- const sy = worldToScreen(0, wy).y;
65370
- if (sy < R) continue;
65371
- const isMajor = Math.abs(wy % tickStep) < .01;
65372
- const isMid = !isMajor && Math.abs(wy % (tickStep / 2)) < .01 && minorDiv >= 4;
65373
- const tickH = isMajor ? R * .7 : isMid ? R * .45 : R * .25;
65374
- const isOrigin = Math.abs(wy) < .01;
65375
- ctx.strokeStyle = isOrigin ? "#ef4444" : isMajor ? "#9ca3af" : "#d1d5db";
65376
- ctx.lineWidth = isOrigin ? 1.5 : isMajor ? 1 : .5;
65377
- ctx.beginPath();
65378
- ctx.moveTo(R, sy);
65379
- ctx.lineTo(R - tickH, sy);
65380
- ctx.stroke();
65381
- if (isMajor) {
65382
- const label = isOrigin ? "0" : rulerLabel(wy, tickStep, isImperial);
65383
- ctx.save();
65384
- ctx.translate(R - 3, sy);
65385
- ctx.rotate(-Math.PI / 2);
65386
- ctx.textAlign = "center";
65387
- ctx.textBaseline = "bottom";
65388
- ctx.fillStyle = isOrigin ? "#ef4444" : "#6b7280";
65389
- ctx.font = `${fontSize}px sans-serif`;
65390
- ctx.fillText(label, 0, 0);
65391
- ctx.restore();
65392
- }
65393
- }
65394
- ctx.fillStyle = "#e5e7eb";
65395
- ctx.fillRect(0, 0, R, R);
65396
- ctx.strokeStyle = "#d1d5db";
65397
- ctx.lineWidth = 1;
65398
- ctx.strokeRect(0, 0, R, R);
65399
- ctx.strokeStyle = "#ef4444";
65400
- ctx.lineWidth = 1;
65401
- const cx = R / 2, cy = R / 2;
65402
- ctx.beginPath();
65403
- ctx.moveTo(cx - 4, cy);
65404
- ctx.lineTo(cx + 4, cy);
65405
- ctx.moveTo(cx, cy - 4);
65406
- ctx.lineTo(cx, cy + 4);
65407
- ctx.stroke();
65408
- const mScreen = worldToScreen(get(mousePos).x, get(mousePos).y);
65409
- if (mScreen.x > R) {
65410
- ctx.strokeStyle = "rgba(59,130,246,0.5)";
65411
- ctx.lineWidth = 1;
65412
- ctx.beginPath();
65413
- ctx.moveTo(mScreen.x, 0);
65414
- ctx.lineTo(mScreen.x, R);
65415
- ctx.stroke();
65416
- ctx.fillStyle = "#3b82f6";
65417
- ctx.beginPath();
65418
- ctx.moveTo(mScreen.x, R);
65419
- ctx.lineTo(mScreen.x - 3, R - 6);
65420
- ctx.lineTo(mScreen.x + 3, R - 6);
65421
- ctx.closePath();
65422
- ctx.fill();
65423
- }
65424
- if (mScreen.y > R) {
65425
- ctx.strokeStyle = "rgba(59,130,246,0.5)";
65426
- ctx.lineWidth = 1;
65427
- ctx.beginPath();
65428
- ctx.moveTo(0, mScreen.y);
65429
- ctx.lineTo(R, mScreen.y);
65430
- ctx.stroke();
65431
- ctx.fillStyle = "#3b82f6";
65432
- ctx.beginPath();
65433
- ctx.moveTo(R, mScreen.y);
65434
- ctx.lineTo(R - 6, mScreen.y - 3);
65435
- ctx.lineTo(R - 6, mScreen.y + 3);
65436
- ctx.closePath();
65437
- ctx.fill();
65438
- }
65439
- ctx.restore();
65440
- }
65441
65201
  function drawBackgroundImage() {
65442
65202
  var _$$get2;
65443
65203
  if (!get(bgImage) || !((_$$get2 = get(currentFloor)) === null || _$$get2 === void 0 ? void 0 : _$$get2.backgroundImage)) return;
@@ -65452,6 +65212,40 @@ function FloorPlanCanvas($$anchor, $$props) {
65452
65212
  ctx.drawImage(get(bgImage), -sw / 2, -sh / 2, sw, sh);
65453
65213
  ctx.restore();
65454
65214
  }
65215
+ function getFloorWallBounds(floor = get(currentFloor)) {
65216
+ var _floor$walls;
65217
+ if (!(floor === null || floor === void 0 || (_floor$walls = floor.walls) === null || _floor$walls === void 0 ? void 0 : _floor$walls.length)) return null;
65218
+ let minX = Infinity;
65219
+ let maxX = -Infinity;
65220
+ let minY = Infinity;
65221
+ let maxY = -Infinity;
65222
+ for (const wall of floor.walls) {
65223
+ minX = Math.min(minX, wall.start.x, wall.end.x);
65224
+ maxX = Math.max(maxX, wall.start.x, wall.end.x);
65225
+ minY = Math.min(minY, wall.start.y, wall.end.y);
65226
+ maxY = Math.max(maxY, wall.start.y, wall.end.y);
65227
+ if (wall.curvePoint) {
65228
+ minX = Math.min(minX, wall.curvePoint.x);
65229
+ maxX = Math.max(maxX, wall.curvePoint.x);
65230
+ minY = Math.min(minY, wall.curvePoint.y);
65231
+ maxY = Math.max(maxY, wall.curvePoint.y);
65232
+ }
65233
+ }
65234
+ const width = maxX - minX;
65235
+ const height = maxY - minY;
65236
+ if (width <= 0 || height <= 0) return null;
65237
+ return {
65238
+ minX,
65239
+ minY,
65240
+ maxX,
65241
+ maxY,
65242
+ width,
65243
+ height
65244
+ };
65245
+ }
65246
+ function getCanvasFrameStyle() {
65247
+ return "width: 100%; height: 100%";
65248
+ }
65455
65249
  function draw() {
65456
65250
  if (!ctx) return;
65457
65251
  if (!canvasDirty) {
@@ -65460,11 +65254,6 @@ function FloorPlanCanvas($$anchor, $$props) {
65460
65254
  }
65461
65255
  canvasDirty = false;
65462
65256
  ctx.clearRect(0, 0, get(width), get(height));
65463
- if (!$$props.viewOnly) {
65464
- ctx.fillStyle = "#f8f9fa";
65465
- ctx.fillRect(0, 0, get(width), get(height));
65466
- drawGrid();
65467
- }
65468
65257
  if (!$$props.viewOnly && get(layerVis).guides) drawGuides$1();
65469
65258
  drawBackgroundImage();
65470
65259
  const floor = get(currentFloor);
@@ -65472,6 +65261,10 @@ function FloorPlanCanvas($$anchor, $$props) {
65472
65261
  requestAnimationFrame(draw);
65473
65262
  return;
65474
65263
  }
65264
+ if (needsFitToCanvas) {
65265
+ zoomToFit();
65266
+ needsFitToCanvas = false;
65267
+ }
65475
65268
  if (get(wallStart) || get(draggingFurnitureId) || get(draggingDoorId) || get(draggingWindowId) || get(draggingStairId) || get(draggingColumnId) || get(draggingWallEndpoint) || get(draggingWallParallel) || get(draggingCurveHandle) || get(draggingHandle) || get(draggingMultiSelect) || get(draggingRoomId) || get(draggingRoomLabelId) || get(draggingTextAnnotationId) || get(draggingGuideId) || get(measuring) || get(annotating) || get(currentPlacingId) || get(isPlacingStair) || get(isPlacingColumn) || get(marqueeStart) || get(isPanning)) canvasDirty = true;
65476
65269
  updateDetectedRooms();
65477
65270
  const selId = get(currentSelectedId);
@@ -66102,7 +65895,6 @@ function FloorPlanCanvas($$anchor, $$props) {
66102
65895
  ctx.setLineDash([]);
66103
65896
  ctx.restore();
66104
65897
  }
66105
- drawRulers();
66106
65898
  drawMinimap$1();
66107
65899
  requestAnimationFrame(draw);
66108
65900
  }
@@ -66117,14 +65909,10 @@ function FloorPlanCanvas($$anchor, $$props) {
66117
65909
  const unsub1 = activeFloor.subscribe((f) => {
66118
65910
  set(currentFloor, f, true);
66119
65911
  markDirty();
66120
- if ($$props.viewOnly && f) requestAnimationFrame(() => {
66121
- zoomToFit();
66122
- });
65912
+ if ($$props.viewOnly && f) needsFitToCanvas = true;
66123
65913
  if (!initialFitDone && f && f.walls.length > 0) {
66124
65914
  initialFitDone = true;
66125
- requestAnimationFrame(() => {
66126
- zoomToFit();
66127
- });
65915
+ needsFitToCanvas = true;
66128
65916
  }
66129
65917
  });
66130
65918
  const unsub2 = selectedElementId.subscribe((id) => {
@@ -66258,130 +66046,1136 @@ function FloorPlanCanvas($$anchor, $$props) {
66258
66046
  };
66259
66047
  });
66260
66048
  user_effect(() => {
66049
+ if (!get(currentFloor)) return;
66261
66050
  setInterval(() => {
66262
66051
  markDirty();
66263
- const heatmapMatrix = createRandomMatrix(20);
66264
- set(currentFloor, {
66265
- ...get(currentFloor),
66266
- furniture: get(currentFloor).furniture.map((item) => {
66267
- if (item.catalogId === "camera") return {
66268
- ...item,
66269
- heatmapMatrix
66270
- };
66271
- return item;
66272
- })
66273
- }, true);
66274
- console.log("currentFloor", get(currentFloor));
66275
- }, 5e3);
66276
- });
66277
- /** Compute world bounding box of all elements */
66278
- function getWorldBBox() {
66279
- if (!get(currentFloor)) return null;
66280
- let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
66281
- let found = false;
66282
- function expand(x, y) {
66283
- if (x < minX) minX = x;
66284
- if (x > maxX) maxX = x;
66285
- if (y < minY) minY = y;
66286
- if (y > maxY) maxY = y;
66287
- found = true;
66288
- }
66289
- for (const w of get(currentFloor).walls) {
66290
- expand(w.start.x, w.start.y);
66291
- expand(w.end.x, w.end.y);
66292
- if (w.curvePoint) expand(w.curvePoint.x, w.curvePoint.y);
66293
- }
66294
- for (const fi of get(currentFloor).furniture) {
66295
- var _fi$width, _fi$depth;
66296
- const cat = getCatalogItem(fi.catalogId);
66297
- if (!cat) continue;
66298
- const r = Math.hypot(((_fi$width = fi.width) !== null && _fi$width !== void 0 ? _fi$width : cat.width) / 2, ((_fi$depth = fi.depth) !== null && _fi$depth !== void 0 ? _fi$depth : cat.depth) / 2);
66299
- expand(fi.position.x - r, fi.position.y - r);
66300
- expand(fi.position.x + r, fi.position.y + r);
66301
- }
66302
- if (get(currentFloor).stairs) for (const st of get(currentFloor).stairs) {
66303
- expand(st.position.x - st.width / 2, st.position.y - st.depth / 2);
66304
- expand(st.position.x + st.width / 2, st.position.y + st.depth / 2);
66305
- }
66306
- if (get(currentFloor).columns) for (const col of get(currentFloor).columns) {
66307
- const r = col.diameter / 2;
66308
- expand(col.position.x - r, col.position.y - r);
66309
- expand(col.position.x + r, col.position.y + r);
66310
- }
66311
- if (!found) return null;
66312
- const pad = 50;
66313
- return {
66314
- minX: minX - pad,
66315
- minY: minY - pad,
66316
- maxX: maxX + pad,
66317
- maxY: maxY + pad
66318
- };
66319
- }
66320
- function drawMinimap$1() {
66321
- if (!get(showMinimap) || !minimapCanvas || !get(currentFloor)) return;
66322
- drawMinimap(getCS(), minimapCanvas, get(currentFloor), getWorldBBox);
66323
- }
66324
- function onMinimapClick(e) {
66325
- if (!minimapCanvas || !get(currentFloor)) return;
66326
- const rect = minimapCanvas.getBoundingClientRect();
66327
- const mx = e.clientX - rect.left;
66328
- const my = e.clientY - rect.top;
66329
- const mw = minimapCanvas.width;
66330
- const mh = minimapCanvas.height;
66331
- const bbox = getWorldBBox();
66332
- if (!bbox) return;
66333
- const bw = bbox.maxX - bbox.minX;
66334
- const bh = bbox.maxY - bbox.minY;
66335
- if (bw < 1 || bh < 1) return;
66336
- const scale = Math.min((mw - 8) / bw, (mh - 8) / bh);
66337
- const ox = (mw - bw * scale) / 2;
66338
- const oy = (mh - bh * scale) / 2;
66339
- set(camX, bbox.minX + (mx - ox) / scale);
66340
- set(camY, bbox.minY + (my - oy) / scale);
66341
- }
66342
- function zoomToFit() {
66343
- if (!get(currentFloor) || get(currentFloor).walls.length === 0 && get(currentFloor).furniture.length === 0) {
66344
- set(camX, 0);
66345
- set(camY, 0);
66346
- set(zoom, 1);
66347
- return;
66348
- }
66349
- let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
66350
- function expand(x, y) {
66351
- if (x < minX) minX = x;
66352
- if (x > maxX) maxX = x;
66353
- if (y < minY) minY = y;
66354
- if (y > maxY) maxY = y;
66355
- }
66356
- for (const w of get(currentFloor).walls) {
66357
- expand(w.start.x, w.start.y);
66358
- expand(w.end.x, w.end.y);
66359
- if (w.curvePoint) expand(w.curvePoint.x, w.curvePoint.y);
66360
- }
66361
- for (const fi of get(currentFloor).furniture) {
66362
- var _fi$width2, _fi$depth2;
66363
- const cat = getCatalogItem(fi.catalogId);
66052
+ const heatmapMatrix = [
66053
+ [
66054
+ 0,
66055
+ 0,
66056
+ 0,
66057
+ 0,
66058
+ 0,
66059
+ 0,
66060
+ 0,
66061
+ 0,
66062
+ 0,
66063
+ 0,
66064
+ 0,
66065
+ 0,
66066
+ 0,
66067
+ 0,
66068
+ 0,
66069
+ 0,
66070
+ 0,
66071
+ 0,
66072
+ 0,
66073
+ 0,
66074
+ 0,
66075
+ 0,
66076
+ 0,
66077
+ 0,
66078
+ 0,
66079
+ 0,
66080
+ 0,
66081
+ 0,
66082
+ 0,
66083
+ 0,
66084
+ 0,
66085
+ 0
66086
+ ],
66087
+ [
66088
+ 0,
66089
+ 0,
66090
+ 0,
66091
+ 0,
66092
+ 0,
66093
+ 0,
66094
+ 0,
66095
+ 0,
66096
+ 0,
66097
+ 0,
66098
+ 0,
66099
+ 0,
66100
+ 0,
66101
+ 0,
66102
+ 0,
66103
+ 0,
66104
+ 0,
66105
+ 0,
66106
+ 0,
66107
+ 0,
66108
+ 0,
66109
+ 0,
66110
+ 0,
66111
+ 0,
66112
+ 0,
66113
+ 0,
66114
+ 0,
66115
+ 0,
66116
+ 0,
66117
+ 0,
66118
+ 0,
66119
+ 0
66120
+ ],
66121
+ [
66122
+ 0,
66123
+ 0,
66124
+ 0,
66125
+ 0,
66126
+ 0,
66127
+ 0,
66128
+ 0,
66129
+ 0,
66130
+ 0,
66131
+ 0,
66132
+ 0,
66133
+ 0,
66134
+ 0,
66135
+ 0,
66136
+ 0,
66137
+ 0,
66138
+ 0,
66139
+ 0,
66140
+ 0,
66141
+ 0,
66142
+ 0,
66143
+ 0,
66144
+ 0,
66145
+ 0,
66146
+ 0,
66147
+ 0,
66148
+ 0,
66149
+ 0,
66150
+ 0,
66151
+ 0,
66152
+ 0,
66153
+ 0
66154
+ ],
66155
+ [
66156
+ 0,
66157
+ 0,
66158
+ 0,
66159
+ 0,
66160
+ 0,
66161
+ 0,
66162
+ 0,
66163
+ 0,
66164
+ 0,
66165
+ 0,
66166
+ 0,
66167
+ 0,
66168
+ 0,
66169
+ 0,
66170
+ 0,
66171
+ 0,
66172
+ 0,
66173
+ 0,
66174
+ 0,
66175
+ 0,
66176
+ 0,
66177
+ 0,
66178
+ 0,
66179
+ 0,
66180
+ 0,
66181
+ 0,
66182
+ 0,
66183
+ 0,
66184
+ 0,
66185
+ 0,
66186
+ 0,
66187
+ 0
66188
+ ],
66189
+ [
66190
+ 0,
66191
+ 0,
66192
+ 0,
66193
+ 0,
66194
+ 0,
66195
+ 0,
66196
+ 0,
66197
+ 0,
66198
+ 0,
66199
+ 0,
66200
+ 0,
66201
+ 0,
66202
+ 0,
66203
+ 0,
66204
+ 0,
66205
+ 0,
66206
+ 0,
66207
+ 0,
66208
+ 0,
66209
+ 0,
66210
+ 0,
66211
+ 0,
66212
+ 0,
66213
+ 0,
66214
+ 0,
66215
+ 0,
66216
+ 0,
66217
+ 0,
66218
+ 0,
66219
+ 0,
66220
+ 0,
66221
+ 0
66222
+ ],
66223
+ [
66224
+ 0,
66225
+ 0,
66226
+ 0,
66227
+ 0,
66228
+ 0,
66229
+ 0,
66230
+ 0,
66231
+ 0,
66232
+ 0,
66233
+ 0,
66234
+ 0,
66235
+ 0,
66236
+ 0,
66237
+ 0,
66238
+ 0,
66239
+ 0,
66240
+ 0,
66241
+ 0,
66242
+ 0,
66243
+ 0,
66244
+ 0,
66245
+ 0,
66246
+ 0,
66247
+ 0,
66248
+ 0,
66249
+ 0,
66250
+ 0,
66251
+ 0,
66252
+ 0,
66253
+ 0,
66254
+ 0,
66255
+ 0
66256
+ ],
66257
+ [
66258
+ 0,
66259
+ 0,
66260
+ 0,
66261
+ 0,
66262
+ 0,
66263
+ 0,
66264
+ 0,
66265
+ 0,
66266
+ 0,
66267
+ 0,
66268
+ 0,
66269
+ 0,
66270
+ 0,
66271
+ 0,
66272
+ 0,
66273
+ 0,
66274
+ 0,
66275
+ 0,
66276
+ 0,
66277
+ 0,
66278
+ 0,
66279
+ 0,
66280
+ 0,
66281
+ 0,
66282
+ 0,
66283
+ 0,
66284
+ 0,
66285
+ 0,
66286
+ 0,
66287
+ 0,
66288
+ 0,
66289
+ 0
66290
+ ],
66291
+ [
66292
+ 0,
66293
+ 0,
66294
+ 0,
66295
+ 0,
66296
+ 0,
66297
+ 0,
66298
+ 0,
66299
+ 0,
66300
+ 0,
66301
+ 0,
66302
+ 0,
66303
+ 0,
66304
+ .3159328774204405,
66305
+ 1.4656853131421907,
66306
+ 2.2380465832282233,
66307
+ 1.4656853131421907,
66308
+ .3159328774204405,
66309
+ 0,
66310
+ 0,
66311
+ 0,
66312
+ 0,
66313
+ 0,
66314
+ 0,
66315
+ 0,
66316
+ 0,
66317
+ 0,
66318
+ 0,
66319
+ 0,
66320
+ 0,
66321
+ 0,
66322
+ 0,
66323
+ 0
66324
+ ],
66325
+ [
66326
+ 0,
66327
+ 0,
66328
+ 0,
66329
+ 0,
66330
+ 0,
66331
+ 0,
66332
+ 0,
66333
+ 0,
66334
+ 0,
66335
+ 0,
66336
+ 0,
66337
+ 0,
66338
+ 1.7489495878144512,
66339
+ 7.010252524548629,
66340
+ 10.597011258282999,
66341
+ 7.010252524548629,
66342
+ 1.7489495878144512,
66343
+ 0,
66344
+ 0,
66345
+ 0,
66346
+ 0,
66347
+ 0,
66348
+ 0,
66349
+ 0,
66350
+ 0,
66351
+ 0,
66352
+ 0,
66353
+ 0,
66354
+ 0,
66355
+ 0,
66356
+ 0,
66357
+ 0
66358
+ ],
66359
+ [
66360
+ 0,
66361
+ 0,
66362
+ 0,
66363
+ 0,
66364
+ 0,
66365
+ 0,
66366
+ 0,
66367
+ 0,
66368
+ 0,
66369
+ 0,
66370
+ 0,
66371
+ 0,
66372
+ 3.3289241086779624,
66373
+ 13.46177725998435,
66374
+ 20.235236701064228,
66375
+ 13.590541779525635,
66376
+ 3.4380594435639265,
66377
+ .00915612667564332,
66378
+ 0,
66379
+ 0,
66380
+ 0,
66381
+ 0,
66382
+ 0,
66383
+ 0,
66384
+ 0,
66385
+ 0,
66386
+ 0,
66387
+ 0,
66388
+ 0,
66389
+ 0,
66390
+ 0,
66391
+ 0
66392
+ ],
66393
+ [
66394
+ 0,
66395
+ 0,
66396
+ 0,
66397
+ 0,
66398
+ 0,
66399
+ 0,
66400
+ 0,
66401
+ 0,
66402
+ 0,
66403
+ 0,
66404
+ 0,
66405
+ 0,
66406
+ 3.2148496888753932,
66407
+ 13.320879325153319,
66408
+ 21.57578250930066,
66409
+ 16.342286624307704,
66410
+ 5.569414220457003,
66411
+ .6079740421039851,
66412
+ 0,
66413
+ 0,
66414
+ 0,
66415
+ 0,
66416
+ 0,
66417
+ 0,
66418
+ 0,
66419
+ 0,
66420
+ 0,
66421
+ 0,
66422
+ 0,
66423
+ 0,
66424
+ 0,
66425
+ 0
66426
+ ],
66427
+ [
66428
+ 0,
66429
+ 0,
66430
+ 0,
66431
+ 0,
66432
+ 0,
66433
+ 0,
66434
+ 0,
66435
+ 0,
66436
+ 0,
66437
+ 0,
66438
+ 0,
66439
+ 0,
66440
+ 1.471089931923573,
66441
+ 8.2191207324426,
66442
+ 17.838951126796992,
66443
+ 19.032501579269645,
66444
+ 10.168729572784246,
66445
+ 2.183833478003975,
66446
+ 0,
66447
+ 0,
66448
+ 0,
66449
+ 0,
66450
+ 0,
66451
+ 0,
66452
+ 0,
66453
+ 0,
66454
+ 0,
66455
+ 0,
66456
+ 0,
66457
+ 0,
66458
+ 0,
66459
+ 0
66460
+ ],
66461
+ [
66462
+ 0,
66463
+ 0,
66464
+ 0,
66465
+ 0,
66466
+ 0,
66467
+ 0,
66468
+ 0,
66469
+ 0,
66470
+ 0,
66471
+ 0,
66472
+ 0,
66473
+ 0,
66474
+ .30224323366570666,
66475
+ 4.469359740497559,
66476
+ 14.670431219686673,
66477
+ 20.333387296969498,
66478
+ 13.054592947321611,
66479
+ 3.1902302512972374,
66480
+ 0,
66481
+ 0,
66482
+ 0,
66483
+ 0,
66484
+ 0,
66485
+ 0,
66486
+ 0,
66487
+ 0,
66488
+ 0,
66489
+ 0,
66490
+ 0,
66491
+ 0,
66492
+ 0,
66493
+ 0
66494
+ ],
66495
+ [
66496
+ 0,
66497
+ 0,
66498
+ 0,
66499
+ 0,
66500
+ 0,
66501
+ 0,
66502
+ 0,
66503
+ .8712958885928778,
66504
+ 4.101109796621668,
66505
+ 7.049595450791787,
66506
+ 6.013717307819157,
66507
+ 2.4950259463993585,
66508
+ .44436828921160365,
66509
+ 2.3964385376201838,
66510
+ 8.995383597734405,
66511
+ 13.185675552510842,
66512
+ 8.716708041551543,
66513
+ 2.1623510704265803,
66514
+ 0,
66515
+ 0,
66516
+ 0,
66517
+ 0,
66518
+ 0,
66519
+ 0,
66520
+ 0,
66521
+ 0,
66522
+ 0,
66523
+ 0,
66524
+ 0,
66525
+ 0,
66526
+ 0,
66527
+ 0
66528
+ ],
66529
+ [
66530
+ 0,
66531
+ 0,
66532
+ 0,
66533
+ 0,
66534
+ 0,
66535
+ 0,
66536
+ 0,
66537
+ 3.62130425013895,
66538
+ 16.246445581668944,
66539
+ 28.185625524032776,
66540
+ 24.0135529219635,
66541
+ 9.834207494427838,
66542
+ 1.5755845092412992,
66543
+ .7273170478700652,
66544
+ 2.61589141718046,
66545
+ 3.749571783336128,
66546
+ 2.426392038976114,
66547
+ .5824057586549773,
66548
+ 0,
66549
+ 0,
66550
+ 0,
66551
+ 0,
66552
+ 0,
66553
+ 0,
66554
+ 0,
66555
+ 0,
66556
+ .5421635625869271,
66557
+ 2.2065200861983407,
66558
+ 3.342547381956746,
66559
+ 2.2065200861983407,
66560
+ .5421635625869271,
66561
+ 0
66562
+ ],
66563
+ [
66564
+ 0,
66565
+ 0,
66566
+ 0,
66567
+ 0,
66568
+ 0,
66569
+ 0,
66570
+ 0,
66571
+ 5.549901318362378,
66572
+ 24.32853931235515,
66573
+ 42.36138150541803,
66574
+ 35.94102328030143,
66575
+ 14.818839539693103,
66576
+ 2.3194161353148814,
66577
+ .05101033364693949,
66578
+ .16491621404182252,
66579
+ .1777607033571859,
66580
+ .12032812505256472,
66581
+ .017569266904996134,
66582
+ 0,
66583
+ 0,
66584
+ 0,
66585
+ 0,
66586
+ 0,
66587
+ 0,
66588
+ 0,
66589
+ 0,
66590
+ 2.9576258950346093,
66591
+ 11.84562175292669,
66592
+ 17.787556061594508,
66593
+ 11.84562175292669,
66594
+ 2.9576258950346093,
66595
+ 0
66596
+ ],
66597
+ [
66598
+ 0,
66599
+ 0,
66600
+ 0,
66601
+ 0,
66602
+ 0,
66603
+ 0,
66604
+ 0,
66605
+ 3.62130425013895,
66606
+ 16.246445581668944,
66607
+ 28.185625524032776,
66608
+ 24.0135529219635,
66609
+ 9.834207494427838,
66610
+ 1.5309964202520414,
66611
+ 0,
66612
+ 0,
66613
+ 0,
66614
+ 0,
66615
+ 0,
66616
+ 0,
66617
+ 0,
66618
+ 0,
66619
+ 0,
66620
+ 0,
66621
+ 0,
66622
+ 0,
66623
+ 0,
66624
+ 6.348491293238841,
66625
+ 25.309150516517526,
66626
+ 37.96250650263207,
66627
+ 25.309150516517526,
66628
+ 6.348491293238841,
66629
+ 0
66630
+ ],
66631
+ [
66632
+ 0,
66633
+ 0,
66634
+ 0,
66635
+ 0,
66636
+ .32082320386030533,
66637
+ 1.2199857338206974,
66638
+ 1.8460462046420483,
66639
+ 2.1325554284523793,
66640
+ 4.379383234527166,
66641
+ 7.049595450791787,
66642
+ 6.013717307819157,
66643
+ 2.4950259463993585,
66644
+ .3886331779750314,
66645
+ 0,
66646
+ 0,
66647
+ 0,
66648
+ 0,
66649
+ 0,
66650
+ 0,
66651
+ 0,
66652
+ 0,
66653
+ 0,
66654
+ 0,
66655
+ 0,
66656
+ 0,
66657
+ 0,
66658
+ 6.723278406098134,
66659
+ 26.889274492038524,
66660
+ 40.34693760289919,
66661
+ 26.889274492038524,
66662
+ 6.723278406098134,
66663
+ 0
66664
+ ],
66665
+ [
66666
+ 0,
66667
+ 0,
66668
+ 0,
66669
+ 0,
66670
+ 2.2804956914871695,
66671
+ 8.96059158937199,
66672
+ 13.408676109914708,
66673
+ 8.96059158937199,
66674
+ 2.2804956914871695,
66675
+ 0,
66676
+ 0,
66677
+ 0,
66678
+ 0,
66679
+ 0,
66680
+ 0,
66681
+ 0,
66682
+ 0,
66683
+ 0,
66684
+ 0,
66685
+ 0,
66686
+ 0,
66687
+ 0,
66688
+ 0,
66689
+ 0,
66690
+ 0,
66691
+ 0,
66692
+ 3.610311889272976,
66693
+ 14.18903058720386,
66694
+ 21.35656319734618,
66695
+ 15.52310871608614,
66696
+ 8.830853849884093,
66697
+ 7.821632516665724
66698
+ ],
66699
+ [
66700
+ 0,
66701
+ 0,
66702
+ 0,
66703
+ 0,
66704
+ 5.861518314504249,
66705
+ 23.379493778146163,
66706
+ 35.09863018520233,
66707
+ 23.379493778146163,
66708
+ 5.861518314504249,
66709
+ 0,
66710
+ 0,
66711
+ 0,
66712
+ 0,
66713
+ 0,
66714
+ 0,
66715
+ 0,
66716
+ 0,
66717
+ 0,
66718
+ 0,
66719
+ 0,
66720
+ 0,
66721
+ 0,
66722
+ 0,
66723
+ 0,
66724
+ 0,
66725
+ 0,
66726
+ .7400359281404749,
66727
+ 3.0082191313345596,
66728
+ 4.511243556428142,
66729
+ 8.25225708991524,
66730
+ 21.61113659978852,
66731
+ 31.371979438413785
66732
+ ],
66733
+ [
66734
+ 0,
66735
+ 0,
66736
+ 0,
66737
+ 0,
66738
+ 7.243115248642567,
66739
+ 28.906850697487346,
66740
+ 43.39219038599119,
66741
+ 28.906850697487346,
66742
+ 7.243115248642567,
66743
+ 0,
66744
+ 0,
66745
+ 0,
66746
+ 0,
66747
+ 0,
66748
+ 0,
66749
+ 0,
66750
+ 0,
66751
+ 0,
66752
+ 0,
66753
+ 0,
66754
+ 0,
66755
+ 0,
66756
+ 0,
66757
+ 0,
66758
+ 0,
66759
+ 0,
66760
+ 0,
66761
+ 0,
66762
+ 0,
66763
+ 7.821632516665724,
66764
+ 31.371979438413785,
66765
+ 46.96473075085739
66766
+ ],
66767
+ [
66768
+ 0,
66769
+ 0,
66770
+ 0,
66771
+ 0,
66772
+ 4.32482477999109,
66773
+ 17.186780480887943,
66774
+ 25.8249366255257,
66775
+ 17.186780480887943,
66776
+ 4.32482477999109,
66777
+ 0,
66778
+ 0,
66779
+ 0,
66780
+ 0,
66781
+ 0,
66782
+ 0,
66783
+ 0,
66784
+ 0,
66785
+ 0,
66786
+ 0,
66787
+ 0,
66788
+ 0,
66789
+ 0,
66790
+ 0,
66791
+ 0,
66792
+ 0,
66793
+ 0,
66794
+ 0,
66795
+ 0,
66796
+ 0,
66797
+ 5.226011941752098,
66798
+ 20.827286571029607,
66799
+ 31.371979438413785
66800
+ ],
66801
+ [
66802
+ 0,
66803
+ 0,
66804
+ 0,
66805
+ 0,
66806
+ 1.0111655316014927,
66807
+ 3.9864631299897444,
66808
+ 5.981469083020068,
66809
+ 3.9864631299897444,
66810
+ 1.0111655316014927,
66811
+ 0,
66812
+ 0,
66813
+ 0,
66814
+ 0,
66815
+ 0,
66816
+ 0,
66817
+ 0,
66818
+ 0,
66819
+ 0,
66820
+ 0,
66821
+ 0,
66822
+ 0,
66823
+ 0,
66824
+ 0,
66825
+ 0,
66826
+ 0,
66827
+ 0,
66828
+ 0,
66829
+ 0,
66830
+ 0,
66831
+ 1.386066255607005,
66832
+ 5.226011941752098,
66833
+ 7.821632516665724
66834
+ ],
66835
+ [
66836
+ 0,
66837
+ 0,
66838
+ 0,
66839
+ 0,
66840
+ 0,
66841
+ 0,
66842
+ 0,
66843
+ 0,
66844
+ 0,
66845
+ 0,
66846
+ 0,
66847
+ 0,
66848
+ 0,
66849
+ 0,
66850
+ 0,
66851
+ 0,
66852
+ 0,
66853
+ 0,
66854
+ 0,
66855
+ 0,
66856
+ 0,
66857
+ 0,
66858
+ 0,
66859
+ 0,
66860
+ 0,
66861
+ 0,
66862
+ 0,
66863
+ 0,
66864
+ 0,
66865
+ 0,
66866
+ 0,
66867
+ 0
66868
+ ],
66869
+ [
66870
+ 0,
66871
+ 0,
66872
+ 0,
66873
+ 0,
66874
+ 0,
66875
+ 0,
66876
+ 0,
66877
+ 0,
66878
+ 0,
66879
+ .05458070912699062,
66880
+ .15528137571229708,
66881
+ .15187574183847025,
66882
+ .06974200470241036,
66883
+ 0,
66884
+ 0,
66885
+ 0,
66886
+ 0,
66887
+ 0,
66888
+ 0,
66889
+ 0,
66890
+ 0,
66891
+ 0,
66892
+ 0,
66893
+ 0,
66894
+ 0,
66895
+ 0,
66896
+ 0,
66897
+ 0,
66898
+ 0,
66899
+ 0,
66900
+ 0,
66901
+ 0
66902
+ ],
66903
+ [
66904
+ 0,
66905
+ 0,
66906
+ 0,
66907
+ 0,
66908
+ 0,
66909
+ 0,
66910
+ 0,
66911
+ 0,
66912
+ .05458070912699062,
66913
+ .2755754209878876,
66914
+ .5707063337010662,
66915
+ .5838714443792508,
66916
+ .31029220828859827,
66917
+ .06974200470241036,
66918
+ 0,
66919
+ 0,
66920
+ 0,
66921
+ 0,
66922
+ .02805561155784787,
66923
+ .8189018232615914,
66924
+ 2.5324966794862513,
66925
+ 3.4377154290206784,
66926
+ 2.1308395665461624,
66927
+ .4650594240098488,
66928
+ 0,
66929
+ 0,
66930
+ 0,
66931
+ 0,
66932
+ 0,
66933
+ 0,
66934
+ 0,
66935
+ 0
66936
+ ],
66937
+ [
66938
+ 0,
66939
+ 0,
66940
+ 0,
66941
+ 0,
66942
+ 0,
66943
+ 0,
66944
+ 0,
66945
+ 0,
66946
+ .08553937100988673,
66947
+ .41228986725093814,
66948
+ .8529789776313961,
66949
+ .8882858218170526,
66950
+ .46357739910366025,
66951
+ .0972950327114796,
66952
+ 0,
66953
+ 0,
66954
+ 0,
66955
+ 0,
66956
+ .3532485267308754,
66957
+ 3.499619222062779,
66958
+ 10.427637306724009,
66959
+ 13.795863309244472,
66960
+ 8.56406987933662,
66961
+ 2.084587966363261,
66962
+ 0,
66963
+ 0,
66964
+ 0,
66965
+ 0,
66966
+ 0,
66967
+ 0,
66968
+ 0,
66969
+ 0
66970
+ ],
66971
+ [
66972
+ 0,
66973
+ 0,
66974
+ 0,
66975
+ 0,
66976
+ 0,
66977
+ 0,
66978
+ 0,
66979
+ 0,
66980
+ .05458070912699062,
66981
+ .2755754209878876,
66982
+ .5707063337010662,
66983
+ .5838714443792508,
66984
+ .31029220828859827,
66985
+ .06974200470241036,
66986
+ 0,
66987
+ 0,
66988
+ 0,
66989
+ .049318035756509136,
66990
+ 1.0607933641418696,
66991
+ 6.758563725967109,
66992
+ 17.660755342385897,
66993
+ 21.973928874871856,
66994
+ 13.201476985075344,
66995
+ 3.101022144002237,
66996
+ 0,
66997
+ 0,
66998
+ 0,
66999
+ 0,
67000
+ 0,
67001
+ 0,
67002
+ 0,
67003
+ 0
67004
+ ],
67005
+ [
67006
+ 0,
67007
+ 0,
67008
+ 0,
67009
+ 0,
67010
+ 0,
67011
+ 0,
67012
+ 0,
67013
+ 0,
67014
+ 0,
67015
+ .05458070912699062,
67016
+ .15528137571229708,
67017
+ .15187574183847025,
67018
+ .06974200470241036,
67019
+ 0,
67020
+ 0,
67021
+ 0,
67022
+ .08786109582645688,
67023
+ .7046356886390628,
67024
+ 3.0107989977663894,
67025
+ 9.51274060076616,
67026
+ 17.749511390220455,
67027
+ 18.26171939391789,
67028
+ 9.630263523792657,
67029
+ 2.084587966363261,
67030
+ 0,
67031
+ 0,
67032
+ 0,
67033
+ 0,
67034
+ 0,
67035
+ 0,
67036
+ 0,
67037
+ 0
67038
+ ],
67039
+ [
67040
+ 0,
67041
+ 0,
67042
+ 0,
67043
+ 0,
67044
+ 0,
67045
+ 0,
67046
+ 0,
67047
+ 0,
67048
+ 0,
67049
+ 0,
67050
+ 0,
67051
+ 0,
67052
+ 1.7382367811803743,
67053
+ 6.78625235876699,
67054
+ 10.215056932817292,
67055
+ 7.28439193353878,
67056
+ 3.243933616660711,
67057
+ 3.1636969367350174,
67058
+ 6.726890242944553,
67059
+ 11.793933219797037,
67060
+ 14.018480108478876,
67061
+ 9.836469200652415,
67062
+ 3.565238303086889,
67063
+ .4650594240098488,
67064
+ 0,
67065
+ 0,
67066
+ 0,
67067
+ 0,
67068
+ 0,
67069
+ 0,
67070
+ 0,
67071
+ 0
67072
+ ],
67073
+ [
67074
+ 0,
67075
+ 0,
67076
+ 0,
67077
+ 0,
67078
+ 0,
67079
+ 0,
67080
+ 0,
67081
+ 0,
67082
+ 0,
67083
+ 0,
67084
+ 0,
67085
+ 0,
67086
+ 6.6983617356443,
67087
+ 26.99436500222664,
67088
+ 41.353519873356255,
67089
+ 29.282163948524662,
67090
+ 11.3741195154941,
67091
+ 7.413346519620399,
67092
+ 10.283468040894338,
67093
+ 11.90128859290927,
67094
+ 9.570529949946668,
67095
+ 4.526681935693334,
67096
+ .8914940911015187,
67097
+ 0,
67098
+ 0,
67099
+ 0,
67100
+ 0,
67101
+ 0,
67102
+ 0,
67103
+ 0,
67104
+ 0,
67105
+ 0
67106
+ ],
67107
+ [
67108
+ 0,
67109
+ 0,
67110
+ 0,
67111
+ 0,
67112
+ 0,
67113
+ 0,
67114
+ 0,
67115
+ 0,
67116
+ 0,
67117
+ 0,
67118
+ 0,
67119
+ 0,
67120
+ 10.047028886051624,
67121
+ 40.69152763227778,
67122
+ 61.87097958316954,
67123
+ 44.034938408633856,
67124
+ 16.762310030892145,
67125
+ 9.760527430556891,
67126
+ 11.69769115898553,
67127
+ 11.007073791008297,
67128
+ 7.176097387403954,
67129
+ 2.7361326724525514,
67130
+ .505476251361877,
67131
+ 0,
67132
+ 0,
67133
+ 0,
67134
+ 0,
67135
+ 0,
67136
+ 0,
67137
+ 0,
67138
+ 0,
67139
+ 0
67140
+ ]
67141
+ ];
67142
+ set(currentFloor, {
67143
+ ...get(currentFloor),
67144
+ furniture: get(currentFloor).furniture.map((item) => {
67145
+ if (item.catalogId === "camera") return {
67146
+ ...item,
67147
+ heatmapMatrix
67148
+ };
67149
+ return item;
67150
+ })
67151
+ }, true);
67152
+ }, 5e3);
67153
+ });
67154
+ /** Compute world bounding box of all elements */
67155
+ function getWorldBBox() {
67156
+ if (!get(currentFloor)) return null;
67157
+ let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
67158
+ let found = false;
67159
+ function expand(x, y) {
67160
+ if (x < minX) minX = x;
67161
+ if (x > maxX) maxX = x;
67162
+ if (y < minY) minY = y;
67163
+ if (y > maxY) maxY = y;
67164
+ found = true;
67165
+ }
67166
+ for (const w of get(currentFloor).walls) {
67167
+ expand(w.start.x, w.start.y);
67168
+ expand(w.end.x, w.end.y);
67169
+ if (w.curvePoint) expand(w.curvePoint.x, w.curvePoint.y);
67170
+ }
67171
+ for (const fi of get(currentFloor).furniture) {
67172
+ var _fi$width, _fi$depth;
67173
+ const cat = getCatalogItem(fi.catalogId);
66364
67174
  if (!cat) continue;
66365
- const hw = ((_fi$width2 = fi.width) !== null && _fi$width2 !== void 0 ? _fi$width2 : cat.width) / 2;
66366
- const hd = ((_fi$depth2 = fi.depth) !== null && _fi$depth2 !== void 0 ? _fi$depth2 : cat.depth) / 2;
66367
- const r = Math.hypot(hw, hd);
67175
+ const r = Math.hypot(((_fi$width = fi.width) !== null && _fi$width !== void 0 ? _fi$width : cat.width) / 2, ((_fi$depth = fi.depth) !== null && _fi$depth !== void 0 ? _fi$depth : cat.depth) / 2);
66368
67176
  expand(fi.position.x - r, fi.position.y - r);
66369
67177
  expand(fi.position.x + r, fi.position.y + r);
66370
67178
  }
66371
- for (const d of get(currentFloor).doors) {
66372
- const w = get(currentFloor).walls.find((wl) => wl.id === d.wallId);
66373
- if (w) {
66374
- const pt = wallPointAt(w, d.position);
66375
- expand(pt.x, pt.y);
66376
- }
66377
- }
66378
- for (const win of get(currentFloor).windows) {
66379
- const w = get(currentFloor).walls.find((wl) => wl.id === win.wallId);
66380
- if (w) {
66381
- const pt = wallPointAt(w, win.position);
66382
- expand(pt.x, pt.y);
66383
- }
66384
- }
66385
67179
  if (get(currentFloor).stairs) for (const st of get(currentFloor).stairs) {
66386
67180
  expand(st.position.x - st.width / 2, st.position.y - st.depth / 2);
66387
67181
  expand(st.position.x + st.width / 2, st.position.y + st.depth / 2);
@@ -66391,18 +67185,67 @@ function FloorPlanCanvas($$anchor, $$props) {
66391
67185
  expand(col.position.x - r, col.position.y - r);
66392
67186
  expand(col.position.x + r, col.position.y + r);
66393
67187
  }
66394
- if (minX === Infinity) {
67188
+ if (!found) return null;
67189
+ const pad = 50;
67190
+ return {
67191
+ minX: minX - pad,
67192
+ minY: minY - pad,
67193
+ maxX: maxX + pad,
67194
+ maxY: maxY + pad
67195
+ };
67196
+ }
67197
+ function drawMinimap$1() {
67198
+ if (!get(showMinimap) || !minimapCanvas || !get(currentFloor)) return;
67199
+ drawMinimap(getCS(), minimapCanvas, get(currentFloor), getWorldBBox);
67200
+ }
67201
+ function onMinimapClick(e) {
67202
+ if (!minimapCanvas || !get(currentFloor)) return;
67203
+ const rect = minimapCanvas.getBoundingClientRect();
67204
+ const mx = e.clientX - rect.left;
67205
+ const my = e.clientY - rect.top;
67206
+ const mw = minimapCanvas.width;
67207
+ const mh = minimapCanvas.height;
67208
+ const bbox = getWorldBBox();
67209
+ if (!bbox) return;
67210
+ const bw = bbox.maxX - bbox.minX;
67211
+ const bh = bbox.maxY - bbox.minY;
67212
+ if (bw < 1 || bh < 1) return;
67213
+ const scale = Math.min((mw - 8) / bw, (mh - 8) / bh);
67214
+ const ox = (mw - bw * scale) / 2;
67215
+ const oy = (mh - bh * scale) / 2;
67216
+ set(camX, bbox.minX + (mx - ox) / scale);
67217
+ set(camY, bbox.minY + (my - oy) / scale);
67218
+ }
67219
+ function zoomToFit() {
67220
+ if (!get(currentFloor)) {
67221
+ set(camX, 0);
67222
+ set(camY, 0);
67223
+ set(zoom, 1);
67224
+ return;
67225
+ }
67226
+ const bounds = getFloorWallBounds(get(currentFloor));
67227
+ if (!bounds) {
66395
67228
  set(camX, 0);
66396
67229
  set(camY, 0);
66397
67230
  set(zoom, 1);
66398
67231
  return;
66399
67232
  }
66400
- const padding = 80;
66401
- const contentW = maxX - minX + padding * 2;
66402
- const contentH = maxY - minY + padding * 2;
66403
- set(camX, (minX + maxX) / 2);
66404
- set(camY, (minY + maxY) / 2);
66405
- set(zoom, Math.min(get(width) / contentW, get(height) / contentH, 3), true);
67233
+ const domWidth = (canvas === null || canvas === void 0 ? void 0 : canvas.clientWidth) || get(width);
67234
+ const domHeight = (canvas === null || canvas === void 0 ? void 0 : canvas.clientHeight) || get(height);
67235
+ if (domWidth > 0 && domHeight > 0) {
67236
+ set(width, domWidth, true);
67237
+ set(height, domHeight, true);
67238
+ if (canvas) {
67239
+ canvas.width = get(width);
67240
+ canvas.height = get(height);
67241
+ }
67242
+ }
67243
+ const padding = 0;
67244
+ const contentW = bounds.width + padding * 2;
67245
+ const contentH = bounds.height + padding * 2;
67246
+ set(camX, (bounds.minX + bounds.maxX) / 2);
67247
+ set(camY, (bounds.minY + bounds.maxY) / 2);
67248
+ set(zoom, Math.max(get(width) / contentW, get(height) / contentH), true);
66406
67249
  set(zoom, Math.max(get(zoom), .1), true);
66407
67250
  markDirty();
66408
67251
  }
@@ -67926,10 +68769,12 @@ function FloorPlanCanvas($$anchor, $$props) {
67926
68769
  var div = root();
67927
68770
  event("keydown", $window, onKeyDown);
67928
68771
  event("keyup", $window, onKeyUp);
67929
- var canvas_1 = child(div);
68772
+ var div_1 = child(div);
68773
+ var canvas_1 = child(div_1);
67930
68774
  let classes;
67931
68775
  bind_this(canvas_1, ($$value) => canvas = $$value, () => canvas);
67932
- var node = sibling(canvas_1, 2);
68776
+ reset(div_1);
68777
+ var node = sibling(div_1, 2);
67933
68778
  var consequent_20 = ($$anchor) => {
67934
68779
  var fragment = root_1$5();
67935
68780
  var node_1 = first_child(fragment);
@@ -68039,8 +68884,8 @@ function FloorPlanCanvas($$anchor, $$props) {
68039
68884
  if_block(node_4, ($$render) => {
68040
68885
  if (get(showMinimap) && get(currentFloor) && get(currentFloor).walls.length > 0) $$render(consequent_3);
68041
68886
  });
68042
- var div_2 = sibling(node_4, 2);
68043
- var node_5 = child(div_2);
68887
+ var div_3 = sibling(node_4, 2);
68888
+ var node_5 = child(div_3);
68044
68889
  var consequent_4 = ($$anchor) => {
68045
68890
  var fragment_1 = root_6();
68046
68891
  var span = first_child(fragment_1);
@@ -68155,11 +69000,11 @@ function FloorPlanCanvas($$anchor, $$props) {
68155
69000
  var text_13 = child(button_6);
68156
69001
  text_13.nodeValue = "🗺 Map";
68157
69002
  reset(button_6);
68158
- reset(div_2);
68159
- var node_11 = sibling(div_2, 2);
69003
+ reset(div_3);
69004
+ var node_11 = sibling(div_3, 2);
68160
69005
  var consequent_10 = ($$anchor) => {
68161
- var div_3 = root_12();
68162
- var node_12 = sibling(child(div_3), 2);
69006
+ var div_4 = root_12();
69007
+ var node_12 = sibling(child(div_4), 2);
68163
69008
  each(node_12, 16, () => [
68164
69009
  ["walls", "Walls"],
68165
69010
  ["doors", "Doors"],
@@ -68200,10 +69045,10 @@ function FloorPlanCanvas($$anchor, $$props) {
68200
69045
  remove_input_defaults(input_4);
68201
69046
  next(2);
68202
69047
  reset(label_3);
68203
- reset(div_3);
69048
+ reset(div_4);
68204
69049
  bind_checked(input_3, () => get(showRoomLabels), ($$value) => set(showRoomLabels, $$value));
68205
69050
  bind_checked(input_4, () => get(showDimensions), ($$value) => set(showDimensions, $$value));
68206
- append($$anchor, div_3);
69051
+ append($$anchor, div_4);
68207
69052
  };
68208
69053
  if_block(node_11, ($$render) => {
68209
69054
  if (get(showLayerPanel)) $$render(consequent_10);
@@ -68244,8 +69089,8 @@ function FloorPlanCanvas($$anchor, $$props) {
68244
69089
  var fragment_4 = comment();
68245
69090
  var node_14 = first_child(fragment_4);
68246
69091
  var consequent_13 = ($$anchor) => {
68247
- var div_4 = root_15();
68248
- var button_7 = child(div_4);
69092
+ var div_5 = root_15();
69093
+ var button_7 = child(div_5);
68249
69094
  var node_15 = sibling(button_7, 2);
68250
69095
  var consequent_11 = ($$anchor) => {
68251
69096
  var button_8 = root_16();
@@ -68271,10 +69116,10 @@ function FloorPlanCanvas($$anchor, $$props) {
68271
69116
  if (get(el).type === "wall" && get(currentSelectedId) && get(currentSelectedIds).size === 0) $$render(consequent_12);
68272
69117
  });
68273
69118
  var button_10 = sibling(node_16, 4);
68274
- reset(div_4);
69119
+ reset(div_5);
68275
69120
  template_effect(() => {
68276
69121
  var _$$get$pos$x;
68277
- return set_style(div_4, `left: ${(_$$get$pos$x = get(el).pos.x) !== null && _$$get$pos$x !== void 0 ? _$$get$pos$x : ""}px; top: ${get(el).pos.y - 44}px; transform: translateX(-50%);`);
69122
+ return set_style(div_5, `left: ${(_$$get$pos$x = get(el).pos.x) !== null && _$$get$pos$x !== void 0 ? _$$get$pos$x : ""}px; top: ${get(el).pos.y - 44}px; transform: translateX(-50%);`);
68278
69123
  });
68279
69124
  delegated("click", button_7, () => {
68280
69125
  if (!get(currentSelectedId) || !get(currentFloor)) return;
@@ -68297,7 +69142,7 @@ function FloorPlanCanvas($$anchor, $$props) {
68297
69142
  selectedElementId.set(null);
68298
69143
  }
68299
69144
  });
68300
- append($$anchor, div_4);
69145
+ append($$anchor, div_5);
68301
69146
  };
68302
69147
  if_block(node_14, ($$render) => {
68303
69148
  if (get(el)) $$render(consequent_13);
@@ -68316,14 +69161,15 @@ function FloorPlanCanvas($$anchor, $$props) {
68316
69161
  });
68317
69162
  var node_18 = sibling(node_17, 2);
68318
69163
  var consequent_16 = ($$anchor) => {
68319
- var div_6 = root_19();
68320
- var text_15 = child(div_6);
68321
- reset(div_6);
69164
+ var div_7 = root_19();
69165
+ var text_15 = child(div_7);
69166
+ reset(div_7);
68322
69167
  template_effect(() => {
68323
69168
  var _$$get13;
68324
- return set_text(text_15, `Click to place · Scroll or R to rotate (${(_$$get13 = get(currentPlacingRotation)) !== null && _$$get13 !== void 0 ? _$$get13 : ""}°) · Esc to cancel`);
69169
+ return set_text(text_15, `Click to place · Scroll or R to rotate (${(_$$get13 = get(currentPlacingRotation)) !== null && _$$get13 !== void 0 ? _$$get13 : ""}°) · Esc
69170
+ to cancel`);
68325
69171
  });
68326
- append($$anchor, div_6);
69172
+ append($$anchor, div_7);
68327
69173
  };
68328
69174
  if_block(node_18, ($$render) => {
68329
69175
  if (get(currentPlacingId) && get(currentTool) === "furniture") $$render(consequent_16);
@@ -68344,24 +69190,24 @@ function FloorPlanCanvas($$anchor, $$props) {
68344
69190
  });
68345
69191
  var node_21 = sibling(node_20, 2);
68346
69192
  var consequent_19 = ($$anchor) => {
68347
- var div_9 = root_22();
68348
- var text_16 = child(div_9);
68349
- reset(div_9);
69193
+ var div_10 = root_22();
69194
+ var text_16 = child(div_10);
69195
+ reset(div_10);
68350
69196
  template_effect(() => set_text(text_16, `${get(annotationStart) ? "Click second point to create annotation" : "Click first point"} · N to exit · Esc to cancel`));
68351
- append($$anchor, div_9);
69197
+ append($$anchor, div_10);
68352
69198
  };
68353
69199
  if_block(node_21, ($$render) => {
68354
69200
  if (get(annotating)) $$render(consequent_19);
68355
69201
  });
68356
- var div_10 = sibling(node_21, 2);
68357
- var button_11 = child(div_10);
69202
+ var div_11 = sibling(node_21, 2);
69203
+ var button_11 = child(div_11);
68358
69204
  var button_12 = sibling(button_11, 2);
68359
69205
  var text_17 = child(button_12);
68360
69206
  reset(button_12);
68361
69207
  var button_13 = sibling(button_12, 2);
68362
69208
  var button_14 = sibling(button_13, 4);
68363
- reset(div_10);
68364
- ContextMenu(sibling(div_10, 2), {
69209
+ reset(div_11);
69210
+ ContextMenu(sibling(div_11, 2), {
68365
69211
  get x() {
68366
69212
  return get(ctxMenuX);
68367
69213
  },
@@ -68436,12 +69282,18 @@ function FloorPlanCanvas($$anchor, $$props) {
68436
69282
  if (!$$props.viewOnly) $$render(consequent_20);
68437
69283
  });
68438
69284
  reset(div);
68439
- template_effect(() => {
68440
- var _$$get14;
69285
+ template_effect(($0) => {
69286
+ set_style(div_1, $0);
68441
69287
  classes = set_class(canvas_1, 1, "block w-full h-full", null, classes, { "pointer-events-none": $$props.viewOnly });
68442
69288
  set_attribute(canvas_1, "tabindex", $$props.viewOnly ? -1 : 0);
68443
- set_style(canvas_1, `cursor: ${(_$$get14 = get(cursorStyle)) !== null && _$$get14 !== void 0 ? _$$get14 : ""}`);
68444
- });
69289
+ set_style(canvas_1, `
69290
+ cursor: ${get(cursorStyle)};
69291
+ max-width: ${$$props.viewOnly ? `${$$props.floorMaxWidth}px` : "unset"};
69292
+ max-height: ${$$props.viewOnly ? `${$$props.floorMaxHeight}px` : "unset"};
69293
+ min-width: ${$$props.viewOnly ? `${$$props.floorMaxWidth}px` : "unset"};
69294
+ min-height: ${$$props.viewOnly ? `${$$props.floorMaxHeight}px` : "unset"};
69295
+ `);
69296
+ }, [() => getCanvasFrameStyle()]);
68445
69297
  delegated("mousedown", canvas_1, onMouseDown);
68446
69298
  delegated("mousemove", canvas_1, onMouseMove);
68447
69299
  delegated("mouseup", canvas_1, onMouseUp);
@@ -69436,7 +70288,11 @@ function App($$anchor, $$props) {
69436
70288
  push($$props, true);
69437
70289
  let showLayers = /* @__PURE__ */ state(false);
69438
70290
  let floorData = /* @__PURE__ */ state(null);
69439
- let config = /* @__PURE__ */ state(proxy({ viewOnly: false }));
70291
+ let config = /* @__PURE__ */ state(proxy({
70292
+ viewOnly: false,
70293
+ floorMaxWidth: 600,
70294
+ floorMaxHeight: 400
70295
+ }));
69440
70296
  (_$$props$stores = $$props.stores) === null || _$$props$stores === void 0 || _$$props$stores.floorData.subscribe((v) => set(floorData, v, true));
69441
70297
  (_$$props$stores2 = $$props.stores) === null || _$$props$stores2 === void 0 || _$$props$stores2.config.subscribe((v) => set(config, v, true));
69442
70298
  let commandPaletteOpen = /* @__PURE__ */ state(false);
@@ -69538,9 +70394,25 @@ function App($$anchor, $$props) {
69538
70394
  var _$$get2;
69539
70395
  return (_$$get2 = get(config)) === null || _$$get2 === void 0 ? void 0 : _$$get2.viewOnly;
69540
70396
  });
69541
- FloorPlanCanvas(node_4, { get viewOnly() {
69542
- return get($0);
69543
- } });
70397
+ let $1 = /* @__PURE__ */ user_derived(() => {
70398
+ var _$$get3;
70399
+ return (_$$get3 = get(config)) === null || _$$get3 === void 0 ? void 0 : _$$get3.floorMaxWidth;
70400
+ });
70401
+ let $2 = /* @__PURE__ */ user_derived(() => {
70402
+ var _$$get4;
70403
+ return (_$$get4 = get(config)) === null || _$$get4 === void 0 ? void 0 : _$$get4.floorMaxHeight;
70404
+ });
70405
+ FloorPlanCanvas(node_4, {
70406
+ get viewOnly() {
70407
+ return get($0);
70408
+ },
70409
+ get floorMaxWidth() {
70410
+ return get($1);
70411
+ },
70412
+ get floorMaxHeight() {
70413
+ return get($2);
70414
+ }
70415
+ });
69544
70416
  }
69545
70417
  var node_5 = sibling(node_4, 2);
69546
70418
  var consequent_2 = ($$anchor) => {