@7365admin1/core 3.83.0 → 3.84.0
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 +24 -0
- package/dist/index.d.ts +250 -1
- package/dist/index.js +195 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +184 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/test/building-map.test.mjs +305 -0
package/dist/index.mjs
CHANGED
|
@@ -59696,6 +59696,179 @@ function createLiftSimulator(options) {
|
|
|
59696
59696
|
};
|
|
59697
59697
|
}
|
|
59698
59698
|
|
|
59699
|
+
// src/utils/building-map.util.ts
|
|
59700
|
+
var WALL_HEIGHT_M = 2.5;
|
|
59701
|
+
var WALL_THICKNESS_M = 0.1;
|
|
59702
|
+
var DEFAULT_SCALE_M_PER_PX = 0.05;
|
|
59703
|
+
function scaleFromMeasurement(pixelDistance, realDistanceM) {
|
|
59704
|
+
if (!Number.isFinite(pixelDistance) || pixelDistance <= 0) {
|
|
59705
|
+
throw new Error("A measurement needs a positive pixel distance.");
|
|
59706
|
+
}
|
|
59707
|
+
if (!Number.isFinite(realDistanceM) || realDistanceM <= 0) {
|
|
59708
|
+
throw new Error("A measurement needs a positive real distance in metres.");
|
|
59709
|
+
}
|
|
59710
|
+
return realDistanceM / pixelDistance;
|
|
59711
|
+
}
|
|
59712
|
+
function vertexDistancePx(a, b) {
|
|
59713
|
+
return Math.hypot(b.x - a.x, b.y - a.y);
|
|
59714
|
+
}
|
|
59715
|
+
function levelScale(level) {
|
|
59716
|
+
const measurement = level.measurements?.find((m) => {
|
|
59717
|
+
const a = level.vertices[m.start];
|
|
59718
|
+
const b = level.vertices[m.end];
|
|
59719
|
+
return a && b && m.distanceM > 0 && vertexDistancePx(a, b) > 0;
|
|
59720
|
+
});
|
|
59721
|
+
if (measurement) {
|
|
59722
|
+
return scaleFromMeasurement(
|
|
59723
|
+
vertexDistancePx(level.vertices[measurement.start], level.vertices[measurement.end]),
|
|
59724
|
+
measurement.distanceM
|
|
59725
|
+
);
|
|
59726
|
+
}
|
|
59727
|
+
return level.scaleMPerPx > 0 ? level.scaleMPerPx : DEFAULT_SCALE_M_PER_PX;
|
|
59728
|
+
}
|
|
59729
|
+
function levelPixelToMetres(level, px, py, imageHeightPx) {
|
|
59730
|
+
const scale = levelScale(level);
|
|
59731
|
+
return {
|
|
59732
|
+
x: level.originXM + px * scale,
|
|
59733
|
+
y: level.originYM + (imageHeightPx - py) * scale
|
|
59734
|
+
};
|
|
59735
|
+
}
|
|
59736
|
+
function levelSolids(level, imageHeightPx) {
|
|
59737
|
+
const toM = (v) => levelPixelToMetres(level, v.x, v.y, imageHeightPx);
|
|
59738
|
+
const walls = [];
|
|
59739
|
+
for (const wall of level.walls ?? []) {
|
|
59740
|
+
const a = level.vertices[wall.start];
|
|
59741
|
+
const b = level.vertices[wall.end];
|
|
59742
|
+
if (!a || !b)
|
|
59743
|
+
continue;
|
|
59744
|
+
const pa = toM(a);
|
|
59745
|
+
const pb = toM(b);
|
|
59746
|
+
const lengthM = Math.hypot(pb.x - pa.x, pb.y - pa.y);
|
|
59747
|
+
if (lengthM <= 0)
|
|
59748
|
+
continue;
|
|
59749
|
+
const heightM = wall.heightM ?? WALL_HEIGHT_M;
|
|
59750
|
+
walls.push({
|
|
59751
|
+
centre: {
|
|
59752
|
+
x: (pa.x + pb.x) / 2,
|
|
59753
|
+
y: (pa.y + pb.y) / 2,
|
|
59754
|
+
// Boxes are centred, so a wall standing ON the floor sits at half its
|
|
59755
|
+
// own height above the level's elevation.
|
|
59756
|
+
z: level.elevationM + heightM / 2
|
|
59757
|
+
},
|
|
59758
|
+
lengthM,
|
|
59759
|
+
thicknessM: wall.thicknessM ?? WALL_THICKNESS_M,
|
|
59760
|
+
heightM,
|
|
59761
|
+
yaw: Math.atan2(pb.y - pa.y, pb.x - pa.x)
|
|
59762
|
+
});
|
|
59763
|
+
}
|
|
59764
|
+
const floors = [];
|
|
59765
|
+
for (const floor of level.floors ?? []) {
|
|
59766
|
+
const points = (floor.vertices ?? []).map((i) => level.vertices[i]).filter(Boolean).map(toM);
|
|
59767
|
+
if (points.length < 3)
|
|
59768
|
+
continue;
|
|
59769
|
+
floors.push({ points, elevationM: level.elevationM, hole: floor.hole === true });
|
|
59770
|
+
}
|
|
59771
|
+
return { level: level.name, elevationM: level.elevationM, walls, floors };
|
|
59772
|
+
}
|
|
59773
|
+
function buildingSolids(map, imageHeightFor) {
|
|
59774
|
+
return (map.levels ?? []).map((level) => levelSolids(level, imageHeightFor(level)));
|
|
59775
|
+
}
|
|
59776
|
+
function wallsFromOccupancyGrid(grid, options) {
|
|
59777
|
+
const threshold = options?.threshold ?? 100;
|
|
59778
|
+
const minRun = Math.max(2, options?.minRunPx ?? 6);
|
|
59779
|
+
const { data, width, height } = grid;
|
|
59780
|
+
if (!width || !height || !data || data.length < width * height) {
|
|
59781
|
+
return { vertices: [], walls: [] };
|
|
59782
|
+
}
|
|
59783
|
+
const occupied = (x, y) => Number(data[y * width + x]) <= threshold;
|
|
59784
|
+
const consumed = new Uint8Array(width * height);
|
|
59785
|
+
const vertices = [];
|
|
59786
|
+
const walls = [];
|
|
59787
|
+
const index = /* @__PURE__ */ new Map();
|
|
59788
|
+
const vertexAt = (x, y) => {
|
|
59789
|
+
const key = `${x}:${y}`;
|
|
59790
|
+
const found = index.get(key);
|
|
59791
|
+
if (found !== void 0)
|
|
59792
|
+
return found;
|
|
59793
|
+
vertices.push({ x, y, z: 0 });
|
|
59794
|
+
index.set(key, vertices.length - 1);
|
|
59795
|
+
return vertices.length - 1;
|
|
59796
|
+
};
|
|
59797
|
+
const addRun = (x1, y1, x2, y2) => {
|
|
59798
|
+
walls.push({ start: vertexAt(x1, y1), end: vertexAt(x2, y2) });
|
|
59799
|
+
};
|
|
59800
|
+
for (let y = 0; y < height; y++) {
|
|
59801
|
+
let run = 0;
|
|
59802
|
+
for (let x = 0; x <= width; x++) {
|
|
59803
|
+
const on = x < width && occupied(x, y);
|
|
59804
|
+
if (on) {
|
|
59805
|
+
run++;
|
|
59806
|
+
continue;
|
|
59807
|
+
}
|
|
59808
|
+
if (run >= minRun) {
|
|
59809
|
+
const startX = x - run;
|
|
59810
|
+
addRun(startX, y, x - 1, y);
|
|
59811
|
+
for (let i = startX; i < x; i++)
|
|
59812
|
+
consumed[y * width + i] = 1;
|
|
59813
|
+
}
|
|
59814
|
+
run = 0;
|
|
59815
|
+
}
|
|
59816
|
+
}
|
|
59817
|
+
for (let x = 0; x < width; x++) {
|
|
59818
|
+
let run = 0;
|
|
59819
|
+
for (let y = 0; y <= height; y++) {
|
|
59820
|
+
const on = y < height && occupied(x, y) && !consumed[y * width + x];
|
|
59821
|
+
if (on) {
|
|
59822
|
+
run++;
|
|
59823
|
+
continue;
|
|
59824
|
+
}
|
|
59825
|
+
if (run >= minRun) {
|
|
59826
|
+
addRun(x, y - run, x, y - 1);
|
|
59827
|
+
}
|
|
59828
|
+
run = 0;
|
|
59829
|
+
}
|
|
59830
|
+
}
|
|
59831
|
+
return { vertices, walls };
|
|
59832
|
+
}
|
|
59833
|
+
function buildingMapFromRobotMaps(name, maps, floorHeightM = 3) {
|
|
59834
|
+
const levels = [...maps ?? []].sort((a, b) => a.floorNo - b.floorNo).map((map) => {
|
|
59835
|
+
const vertices = [];
|
|
59836
|
+
if (map.baseX || map.baseY) {
|
|
59837
|
+
vertices.push({
|
|
59838
|
+
x: map.baseX ?? 0,
|
|
59839
|
+
y: map.baseY ?? 0,
|
|
59840
|
+
z: 0,
|
|
59841
|
+
name: `L${map.floorNo}_charger`,
|
|
59842
|
+
isCharger: true,
|
|
59843
|
+
theta: map.baseTheta ?? 0
|
|
59844
|
+
});
|
|
59845
|
+
}
|
|
59846
|
+
for (const area of map.areaList ?? []) {
|
|
59847
|
+
vertices.push({
|
|
59848
|
+
x: area.x,
|
|
59849
|
+
y: area.y,
|
|
59850
|
+
z: 0,
|
|
59851
|
+
name: area.areaName,
|
|
59852
|
+
isCleaningZone: true
|
|
59853
|
+
});
|
|
59854
|
+
}
|
|
59855
|
+
return {
|
|
59856
|
+
name: map.mapName?.trim() || `L${map.floorNo}`,
|
|
59857
|
+
elevationM: (map.floorNo - 1) * floorHeightM,
|
|
59858
|
+
drawing: { fileKey: map.backgroundFileKey },
|
|
59859
|
+
scaleMPerPx: map.resolution && map.resolution > 0 ? map.resolution : DEFAULT_SCALE_M_PER_PX,
|
|
59860
|
+
originXM: map.originX ?? 0,
|
|
59861
|
+
originYM: map.originY ?? 0,
|
|
59862
|
+
vertices,
|
|
59863
|
+
walls: [],
|
|
59864
|
+
floors: [],
|
|
59865
|
+
doors: [],
|
|
59866
|
+
measurements: []
|
|
59867
|
+
};
|
|
59868
|
+
});
|
|
59869
|
+
return { name, levels, lifts: [] };
|
|
59870
|
+
}
|
|
59871
|
+
|
|
59699
59872
|
// src/services/robot-fleet.service.ts
|
|
59700
59873
|
import { BadRequestError as BadRequestError134, NotFoundError as NotFoundError43 } from "@7365admin1/node-server-utils";
|
|
59701
59874
|
|
|
@@ -93990,6 +94163,7 @@ export {
|
|
|
93990
94163
|
ConsoleAuditAction,
|
|
93991
94164
|
ConsoleAuditTarget,
|
|
93992
94165
|
DEFAULT_RING_SECONDS,
|
|
94166
|
+
DEFAULT_SCALE_M_PER_PX,
|
|
93993
94167
|
DEFAULT_SITE_TIMEZONE,
|
|
93994
94168
|
DEVICE_STATUS,
|
|
93995
94169
|
DOBStatus,
|
|
@@ -94209,6 +94383,8 @@ export {
|
|
|
94209
94383
|
VerificationType,
|
|
94210
94384
|
VisitorSort,
|
|
94211
94385
|
VisitorStatus,
|
|
94386
|
+
WALL_HEIGHT_M,
|
|
94387
|
+
WALL_THICKNESS_M,
|
|
94212
94388
|
addressSchema,
|
|
94213
94389
|
allowedFieldsSite,
|
|
94214
94390
|
allowedNatures,
|
|
@@ -94220,6 +94396,8 @@ export {
|
|
|
94220
94396
|
attendanceSchema,
|
|
94221
94397
|
attendanceSettingsSchema,
|
|
94222
94398
|
buildSelfServiceEmailContext,
|
|
94399
|
+
buildingMapFromRobotMaps,
|
|
94400
|
+
buildingSolids,
|
|
94223
94401
|
building_level_namespace_collection,
|
|
94224
94402
|
building_units_namespace_collection,
|
|
94225
94403
|
buildings_namespace_collection,
|
|
@@ -94326,6 +94504,9 @@ export {
|
|
|
94326
94504
|
isTermsCurrent,
|
|
94327
94505
|
isTrackingStale,
|
|
94328
94506
|
isValidTimezone,
|
|
94507
|
+
levelPixelToMetres,
|
|
94508
|
+
levelScale,
|
|
94509
|
+
levelSolids,
|
|
94329
94510
|
listStaffUserIds,
|
|
94330
94511
|
liveStatusFor,
|
|
94331
94512
|
manpowerDesignationsSchema,
|
|
@@ -94424,6 +94605,7 @@ export {
|
|
|
94424
94605
|
robotTier,
|
|
94425
94606
|
robotTypesVisibleTo,
|
|
94426
94607
|
rtspUrl,
|
|
94608
|
+
scaleFromMeasurement,
|
|
94427
94609
|
schema,
|
|
94428
94610
|
schemaAppSlugNotification,
|
|
94429
94611
|
schemaApprovedBy,
|
|
@@ -94841,8 +95023,10 @@ export {
|
|
|
94841
95023
|
vehicleSchema,
|
|
94842
95024
|
vehicleViewOf,
|
|
94843
95025
|
vehicles_namespace_collection,
|
|
95026
|
+
vertexDistancePx,
|
|
94844
95027
|
visitors_namespace_collection,
|
|
94845
95028
|
wallConfig,
|
|
95029
|
+
wallsFromOccupancyGrid,
|
|
94846
95030
|
withLiveLink,
|
|
94847
95031
|
workOrderSchema,
|
|
94848
95032
|
work_orders2_namespace_collection,
|