@smarterplan/ngx-smarterplan-core 1.4.19 → 1.4.21

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.
Files changed (29) hide show
  1. package/esm2022/lib/helpers.service.mjs +28 -2
  2. package/esm2022/lib/matterport-extensions/security-camera/SecurityCamera.mjs +28 -7
  3. package/esm2022/lib/services/filter.service.mjs +8 -3
  4. package/esm2022/lib/services/matterport-object3d.service.mjs +657 -133
  5. package/esm2022/lib/services/matterport.service.mjs +330 -9
  6. package/esm2022/lib/services/models/base-object.service.mjs +10 -9
  7. package/esm2022/lib/services/models/equipment.service.mjs +27 -2
  8. package/esm2022/lib/services/models/feature.service.mjs +14 -1
  9. package/esm2022/lib/services/models/measurement.service.mjs +17 -1
  10. package/esm2022/lib/services/sweep-locator.service.mjs +114 -0
  11. package/esm2022/lib/services/threejs.service.mjs +840 -35
  12. package/esm2022/lib/services/utils/matterport-framing.util.mjs +63 -0
  13. package/esm2022/lib/services/viewer.service.mjs +193 -10
  14. package/esm2022/lib/types.service.mjs +3 -1
  15. package/esm2022/public-api.mjs +2 -1
  16. package/fesm2022/smarterplan-ngx-smarterplan-core.mjs +2886 -776
  17. package/fesm2022/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
  18. package/lib/helpers.service.d.ts +17 -0
  19. package/lib/services/matterport-object3d.service.d.ts +125 -5
  20. package/lib/services/matterport.service.d.ts +106 -7
  21. package/lib/services/models/base-object.service.d.ts +3 -4
  22. package/lib/services/models/measurement.service.d.ts +1 -0
  23. package/lib/services/sweep-locator.service.d.ts +54 -0
  24. package/lib/services/threejs.service.d.ts +304 -10
  25. package/lib/services/utils/matterport-framing.util.d.ts +40 -0
  26. package/lib/services/viewer.service.d.ts +87 -2
  27. package/lib/types.service.d.ts +42 -1
  28. package/package.json +1 -1
  29. package/public-api.d.ts +1 -0
@@ -0,0 +1,63 @@
1
+ // matterport-framing.util.ts
2
+ /**
3
+ * Camera rotation that shows `target` from `camera`, at a given horizontal place of the viewer.
4
+ * Matterport yaw is 0 when looking toward -Z and grows when turning left; pitch is positive upward.
5
+ * @param horizontalTanHalfFov tan(horizontal FOV / 2), i.e. 1 / projection[0] of the camera pose
6
+ * @param screenX where the target must appear, from -1 (left edge) to 1 (right edge); 0 = center.
7
+ * Used when part of the viewer is covered (side panel), to frame the visible area.
8
+ */
9
+ export function computeFramingRotation(camera, target, horizontalTanHalfFov = 1, screenX = 0) {
10
+ const dx = target.x - camera.x;
11
+ const dy = target.y - camera.y;
12
+ const dz = target.z - camera.z;
13
+ const yawToTarget = Math.atan2(-dx, -dz);
14
+ // the target is seen at screenX when the camera looks that much to its side
15
+ const offset = Math.atan(screenX * horizontalTanHalfFov);
16
+ return {
17
+ x: toDegrees(Math.atan2(dy, Math.hypot(dx, dz))),
18
+ y: toDegrees(yawToTarget + offset),
19
+ };
20
+ }
21
+ /**
22
+ * Horizontal place (-1..1) of the center of the visible part of the viewer.
23
+ * @param viewer client rect of the viewer iframe
24
+ * @param visibleLeft / visibleRight client X bounds of the part not covered by other panels
25
+ */
26
+ export function visibleCenterScreenX(viewer, visibleLeft, visibleRight) {
27
+ if (!viewer.width)
28
+ return 0;
29
+ const left = Math.max(viewer.left, visibleLeft);
30
+ const right = Math.min(viewer.left + viewer.width, visibleRight);
31
+ if (right <= left)
32
+ return 0;
33
+ const center = (left + right) / 2;
34
+ return ((center - viewer.left) / viewer.width) * 2 - 1;
35
+ }
36
+ function toDegrees(rad) {
37
+ return (rad * 180) / Math.PI;
38
+ }
39
+ /** Height of the floor under a sweep: its puck, or 1.5 m under the camera when the SDK gives none */
40
+ export function sweepFloorY(sweep) {
41
+ return sweep.puckPosition?.y ?? sweep.floorPosition?.y ?? sweep.position.y - 1.5;
42
+ }
43
+ /**
44
+ * Sweep closest to an object placed at `position`, among the sweeps of the same storey: the camera
45
+ * of the storey below is often nearer in 3D than a sweep of the same room. A sweep is on the same
46
+ * storey when the object stands between 0.5 m under its floor and 3 m above it; without any such
47
+ * sweep, all of them are considered. Distances are measured horizontally.
48
+ */
49
+ export function pickNearestSweepOnSameStorey(sweeps, position) {
50
+ const sameStorey = sweeps.filter((s) => position.y >= s.floorY - 0.5 && position.y < s.floorY + 3);
51
+ const candidates = sameStorey.length > 0 ? sameStorey : sweeps;
52
+ let best = null;
53
+ let bestDist = Infinity;
54
+ for (const sweep of candidates) {
55
+ const dist = Math.hypot(sweep.position.x - position.x, sweep.position.z - position.z);
56
+ if (dist < bestDist) {
57
+ bestDist = dist;
58
+ best = sweep.sid;
59
+ }
60
+ }
61
+ return best;
62
+ }
63
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0dGVycG9ydC1mcmFtaW5nLnV0aWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc21hcnRlcnBsYW4tY29yZS9zcmMvbGliL3NlcnZpY2VzL3V0aWxzL21hdHRlcnBvcnQtZnJhbWluZy51dGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDZCQUE2QjtBQU83Qjs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsc0JBQXNCLENBQ2xDLE1BQWUsRUFDZixNQUFlLEVBQ2Ysb0JBQW9CLEdBQUcsQ0FBQyxFQUN4QixPQUFPLEdBQUcsQ0FBQztJQUVYLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUMvQixNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDL0IsTUFBTSxFQUFFLEdBQUcsTUFBTSxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQy9CLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN6Qyw0RUFBNEU7SUFDNUUsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEdBQUcsb0JBQW9CLENBQUMsQ0FBQztJQUN6RCxPQUFPO1FBQ0gsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ2hELENBQUMsRUFBRSxTQUFTLENBQUMsV0FBVyxHQUFHLE1BQU0sQ0FBQztLQUNyQyxDQUFDO0FBQ04sQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsb0JBQW9CLENBQ2hDLE1BQXVDLEVBQ3ZDLFdBQW1CLEVBQ25CLFlBQW9CO0lBRXBCLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSztRQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzVCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQztJQUNoRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQztJQUNqRSxJQUFJLEtBQUssSUFBSSxJQUFJO1FBQUUsT0FBTyxDQUFDLENBQUM7SUFDNUIsTUFBTSxNQUFNLEdBQUcsQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2xDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDM0QsQ0FBQztBQUVELFNBQVMsU0FBUyxDQUFDLEdBQVc7SUFDMUIsT0FBTyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQ2pDLENBQUM7QUFFRCxxR0FBcUc7QUFDckcsTUFBTSxVQUFVLFdBQVcsQ0FBQyxLQUE2RTtJQUNyRyxPQUFPLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQyxJQUFJLEtBQUssQ0FBQyxhQUFhLEVBQUUsQ0FBQyxJQUFJLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQztBQUNyRixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsNEJBQTRCLENBQ3hDLE1BQTRELEVBQzVELFFBQWlCO0lBRWpCLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sR0FBRyxHQUFHLElBQUksUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ25HLE1BQU0sVUFBVSxHQUFHLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztJQUMvRCxJQUFJLElBQUksR0FBa0IsSUFBSSxDQUFDO0lBQy9CLElBQUksUUFBUSxHQUFHLFFBQVEsQ0FBQztJQUN4QixLQUFLLE1BQU0sS0FBSyxJQUFJLFVBQVUsRUFBRSxDQUFDO1FBQzdCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEYsSUFBSSxJQUFJLEdBQUcsUUFBUSxFQUFFLENBQUM7WUFDbEIsUUFBUSxHQUFHLElBQUksQ0FBQztZQUNoQixJQUFJLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQztRQUNyQixDQUFDO0lBQ0wsQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBtYXR0ZXJwb3J0LWZyYW1pbmcudXRpbC50c1xuXG5pbXBvcnQgeyBQb2ludDNEIH0gZnJvbSAnLi4vLi4vdHlwZXMuc2VydmljZSc7XG5cbi8qKiBNYXR0ZXJwb3J0IGNhbWVyYSByb3RhdGlvbiwgaW4gZGVncmVlcyAoeDogcGl0Y2gsIHk6IHlhdykgKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ2FtZXJhUm90YXRpb24geyB4OiBudW1iZXI7IHk6IG51bWJlcjsgfVxuXG4vKipcbiAqIENhbWVyYSByb3RhdGlvbiB0aGF0IHNob3dzIGB0YXJnZXRgIGZyb20gYGNhbWVyYWAsIGF0IGEgZ2l2ZW4gaG9yaXpvbnRhbCBwbGFjZSBvZiB0aGUgdmlld2VyLlxuICogTWF0dGVycG9ydCB5YXcgaXMgMCB3aGVuIGxvb2tpbmcgdG93YXJkIC1aIGFuZCBncm93cyB3aGVuIHR1cm5pbmcgbGVmdDsgcGl0Y2ggaXMgcG9zaXRpdmUgdXB3YXJkLlxuICogQHBhcmFtIGhvcml6b250YWxUYW5IYWxmRm92IHRhbihob3Jpem9udGFsIEZPViAvIDIpLCBpLmUuIDEgLyBwcm9qZWN0aW9uWzBdIG9mIHRoZSBjYW1lcmEgcG9zZVxuICogQHBhcmFtIHNjcmVlblggd2hlcmUgdGhlIHRhcmdldCBtdXN0IGFwcGVhciwgZnJvbSAtMSAobGVmdCBlZGdlKSB0byAxIChyaWdodCBlZGdlKTsgMCA9IGNlbnRlci5cbiAqICAgICAgICAgICAgICAgIFVzZWQgd2hlbiBwYXJ0IG9mIHRoZSB2aWV3ZXIgaXMgY292ZXJlZCAoc2lkZSBwYW5lbCksIHRvIGZyYW1lIHRoZSB2aXNpYmxlIGFyZWEuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wdXRlRnJhbWluZ1JvdGF0aW9uKFxuICAgIGNhbWVyYTogUG9pbnQzRCxcbiAgICB0YXJnZXQ6IFBvaW50M0QsXG4gICAgaG9yaXpvbnRhbFRhbkhhbGZGb3YgPSAxLFxuICAgIHNjcmVlblggPSAwXG4pOiBDYW1lcmFSb3RhdGlvbiB7XG4gICAgY29uc3QgZHggPSB0YXJnZXQueCAtIGNhbWVyYS54O1xuICAgIGNvbnN0IGR5ID0gdGFyZ2V0LnkgLSBjYW1lcmEueTtcbiAgICBjb25zdCBkeiA9IHRhcmdldC56IC0gY2FtZXJhLno7XG4gICAgY29uc3QgeWF3VG9UYXJnZXQgPSBNYXRoLmF0YW4yKC1keCwgLWR6KTtcbiAgICAvLyB0aGUgdGFyZ2V0IGlzIHNlZW4gYXQgc2NyZWVuWCB3aGVuIHRoZSBjYW1lcmEgbG9va3MgdGhhdCBtdWNoIHRvIGl0cyBzaWRlXG4gICAgY29uc3Qgb2Zmc2V0ID0gTWF0aC5hdGFuKHNjcmVlblggKiBob3Jpem9udGFsVGFuSGFsZkZvdik7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDogdG9EZWdyZWVzKE1hdGguYXRhbjIoZHksIE1hdGguaHlwb3QoZHgsIGR6KSkpLFxuICAgICAgICB5OiB0b0RlZ3JlZXMoeWF3VG9UYXJnZXQgKyBvZmZzZXQpLFxuICAgIH07XG59XG5cbi8qKlxuICogSG9yaXpvbnRhbCBwbGFjZSAoLTEuLjEpIG9mIHRoZSBjZW50ZXIgb2YgdGhlIHZpc2libGUgcGFydCBvZiB0aGUgdmlld2VyLlxuICogQHBhcmFtIHZpZXdlciBjbGllbnQgcmVjdCBvZiB0aGUgdmlld2VyIGlmcmFtZVxuICogQHBhcmFtIHZpc2libGVMZWZ0IC8gdmlzaWJsZVJpZ2h0IGNsaWVudCBYIGJvdW5kcyBvZiB0aGUgcGFydCBub3QgY292ZXJlZCBieSBvdGhlciBwYW5lbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZpc2libGVDZW50ZXJTY3JlZW5YKFxuICAgIHZpZXdlcjogeyBsZWZ0OiBudW1iZXI7IHdpZHRoOiBudW1iZXIgfSxcbiAgICB2aXNpYmxlTGVmdDogbnVtYmVyLFxuICAgIHZpc2libGVSaWdodDogbnVtYmVyXG4pOiBudW1iZXIge1xuICAgIGlmICghdmlld2VyLndpZHRoKSByZXR1cm4gMDtcbiAgICBjb25zdCBsZWZ0ID0gTWF0aC5tYXgodmlld2VyLmxlZnQsIHZpc2libGVMZWZ0KTtcbiAgICBjb25zdCByaWdodCA9IE1hdGgubWluKHZpZXdlci5sZWZ0ICsgdmlld2VyLndpZHRoLCB2aXNpYmxlUmlnaHQpO1xuICAgIGlmIChyaWdodCA8PSBsZWZ0KSByZXR1cm4gMDtcbiAgICBjb25zdCBjZW50ZXIgPSAobGVmdCArIHJpZ2h0KSAvIDI7XG4gICAgcmV0dXJuICgoY2VudGVyIC0gdmlld2VyLmxlZnQpIC8gdmlld2VyLndpZHRoKSAqIDIgLSAxO1xufVxuXG5mdW5jdGlvbiB0b0RlZ3JlZXMocmFkOiBudW1iZXIpOiBudW1iZXIge1xuICAgIHJldHVybiAocmFkICogMTgwKSAvIE1hdGguUEk7XG59XG5cbi8qKiBIZWlnaHQgb2YgdGhlIGZsb29yIHVuZGVyIGEgc3dlZXA6IGl0cyBwdWNrLCBvciAxLjUgbSB1bmRlciB0aGUgY2FtZXJhIHdoZW4gdGhlIFNESyBnaXZlcyBub25lICovXG5leHBvcnQgZnVuY3Rpb24gc3dlZXBGbG9vclkoc3dlZXA6IHsgcG9zaXRpb246IFBvaW50M0Q7IHB1Y2tQb3NpdGlvbj86IFBvaW50M0Q7IGZsb29yUG9zaXRpb24/OiBQb2ludDNEIH0pOiBudW1iZXIge1xuICAgIHJldHVybiBzd2VlcC5wdWNrUG9zaXRpb24/LnkgPz8gc3dlZXAuZmxvb3JQb3NpdGlvbj8ueSA/PyBzd2VlcC5wb3NpdGlvbi55IC0gMS41O1xufVxuXG4vKipcbiAqIFN3ZWVwIGNsb3Nlc3QgdG8gYW4gb2JqZWN0IHBsYWNlZCBhdCBgcG9zaXRpb25gLCBhbW9uZyB0aGUgc3dlZXBzIG9mIHRoZSBzYW1lIHN0b3JleTogdGhlIGNhbWVyYVxuICogb2YgdGhlIHN0b3JleSBiZWxvdyBpcyBvZnRlbiBuZWFyZXIgaW4gM0QgdGhhbiBhIHN3ZWVwIG9mIHRoZSBzYW1lIHJvb20uIEEgc3dlZXAgaXMgb24gdGhlIHNhbWVcbiAqIHN0b3JleSB3aGVuIHRoZSBvYmplY3Qgc3RhbmRzIGJldHdlZW4gMC41IG0gdW5kZXIgaXRzIGZsb29yIGFuZCAzIG0gYWJvdmUgaXQ7IHdpdGhvdXQgYW55IHN1Y2hcbiAqIHN3ZWVwLCBhbGwgb2YgdGhlbSBhcmUgY29uc2lkZXJlZC4gRGlzdGFuY2VzIGFyZSBtZWFzdXJlZCBob3Jpem9udGFsbHkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwaWNrTmVhcmVzdFN3ZWVwT25TYW1lU3RvcmV5KFxuICAgIHN3ZWVwczogeyBzaWQ6IHN0cmluZzsgcG9zaXRpb246IFBvaW50M0Q7IGZsb29yWTogbnVtYmVyIH1bXSxcbiAgICBwb3NpdGlvbjogUG9pbnQzRFxuKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgY29uc3Qgc2FtZVN0b3JleSA9IHN3ZWVwcy5maWx0ZXIoKHMpID0+IHBvc2l0aW9uLnkgPj0gcy5mbG9vclkgLSAwLjUgJiYgcG9zaXRpb24ueSA8IHMuZmxvb3JZICsgMyk7XG4gICAgY29uc3QgY2FuZGlkYXRlcyA9IHNhbWVTdG9yZXkubGVuZ3RoID4gMCA/IHNhbWVTdG9yZXkgOiBzd2VlcHM7XG4gICAgbGV0IGJlc3Q6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAgIGxldCBiZXN0RGlzdCA9IEluZmluaXR5O1xuICAgIGZvciAoY29uc3Qgc3dlZXAgb2YgY2FuZGlkYXRlcykge1xuICAgICAgICBjb25zdCBkaXN0ID0gTWF0aC5oeXBvdChzd2VlcC5wb3NpdGlvbi54IC0gcG9zaXRpb24ueCwgc3dlZXAucG9zaXRpb24ueiAtIHBvc2l0aW9uLnopO1xuICAgICAgICBpZiAoZGlzdCA8IGJlc3REaXN0KSB7XG4gICAgICAgICAgICBiZXN0RGlzdCA9IGRpc3Q7XG4gICAgICAgICAgICBiZXN0ID0gc3dlZXAuc2lkO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBiZXN0O1xufVxuIl19