cables and noes now render in the bins, the label to show readinds appears when zooming in and inventory using fill percent works, still need to work on top node fill level for cable inventory control, and node heatmap/gradient similar to the bin SVG
This commit is contained in:
parent
cb6609bdb1
commit
ee416db013
9 changed files with 911 additions and 19 deletions
468
package-lock.json
generated
468
package-lock.json
generated
|
|
@ -25,6 +25,7 @@
|
|||
"@mui/styles": "^6.1.6",
|
||||
"@mui/x-date-pickers": "^7.26.0",
|
||||
"@react-pdf/renderer": "^4.3.0",
|
||||
"@react-three/drei": "^9.105.6",
|
||||
"@react-three/fiber": "^8.18.0",
|
||||
"@sentry/react": "^8.38.0",
|
||||
"@turf/area": "^7.2.0",
|
||||
|
|
@ -64,7 +65,7 @@
|
|||
"react-virtualized-auto-sizer": "^1.0.25",
|
||||
"recharts": "^2.15.1",
|
||||
"semver": "^7.7.1",
|
||||
"three": "^0.183.2",
|
||||
"three": "^0.152.2",
|
||||
"victory": "^37.3.6",
|
||||
"weather-icons-react": "^1.2.0"
|
||||
},
|
||||
|
|
@ -2480,6 +2481,12 @@
|
|||
"gl-style-validate": "dist/gl-style-validate.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@mediapipe/tasks-vision": {
|
||||
"version": "0.10.8",
|
||||
"resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.8.tgz",
|
||||
"integrity": "sha512-Rp7ll8BHrKB3wXaRFKhrltwZl1CiXGdibPxuWXvqGnKTnv8fqa/nvftYNuSbf+pbJWKYCXdBtYTITdAUTGGh0Q==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@mui/core-downloads-tracker": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.5.0.tgz",
|
||||
|
|
@ -3232,6 +3239,134 @@
|
|||
"@react-pdf/stylesheet": "^6.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-spring/animated": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.6.1.tgz",
|
||||
"integrity": "sha512-ls/rJBrAqiAYozjLo5EPPLLOb1LM0lNVQcXODTC1SMtS6DbuBCPaKco5svFUQFMP2dso3O+qcC4k9FsKc0KxMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@react-spring/shared": "~9.6.1",
|
||||
"@react-spring/types": "~9.6.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-spring/core": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.6.1.tgz",
|
||||
"integrity": "sha512-3HAAinAyCPessyQNNXe5W0OHzRfa8Yo5P748paPcmMowZ/4sMfaZ2ZB6e5x5khQI8NusOHj8nquoutd6FRY5WQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@react-spring/animated": "~9.6.1",
|
||||
"@react-spring/rafz": "~9.6.1",
|
||||
"@react-spring/shared": "~9.6.1",
|
||||
"@react-spring/types": "~9.6.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/react-spring/donate"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-spring/rafz": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.6.1.tgz",
|
||||
"integrity": "sha512-v6qbgNRpztJFFfSE3e2W1Uz+g8KnIBs6SmzCzcVVF61GdGfGOuBrbjIcp+nUz301awVmREKi4eMQb2Ab2gGgyQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@react-spring/shared": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.6.1.tgz",
|
||||
"integrity": "sha512-PBFBXabxFEuF8enNLkVqMC9h5uLRBo6GQhRMQT/nRTnemVENimgRd+0ZT4yFnAQ0AxWNiJfX3qux+bW2LbG6Bw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@react-spring/rafz": "~9.6.1",
|
||||
"@react-spring/types": "~9.6.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-spring/three": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-spring/three/-/three-9.6.1.tgz",
|
||||
"integrity": "sha512-Tyw2YhZPKJAX3t2FcqvpLRb71CyTe1GvT3V+i+xJzfALgpk10uPGdGaQQ5Xrzmok1340DAeg2pR/MCfaW7b8AA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@react-spring/animated": "~9.6.1",
|
||||
"@react-spring/core": "~9.6.1",
|
||||
"@react-spring/shared": "~9.6.1",
|
||||
"@react-spring/types": "~9.6.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-three/fiber": ">=6.0",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"three": ">=0.126"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-spring/types": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.6.1.tgz",
|
||||
"integrity": "sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@react-three/drei": {
|
||||
"version": "9.105.6",
|
||||
"resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.105.6.tgz",
|
||||
"integrity": "sha512-JBgYeV36N9N9f1c3o1ZfLYW4rXZA7UQTq32Y8s3DEF6lwj1/y+RP/yq2VG5I8OzUPl7gsmWdy8fpWZgrlAqUpQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"@mediapipe/tasks-vision": "0.10.8",
|
||||
"@monogrid/gainmap-js": "^3.0.5",
|
||||
"@react-spring/three": "~9.6.1",
|
||||
"@use-gesture/react": "^10.2.24",
|
||||
"camera-controls": "^2.4.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"detect-gpu": "^5.0.28",
|
||||
"glsl-noise": "^0.0.0",
|
||||
"hls.js": "1.3.5",
|
||||
"maath": "^0.10.7",
|
||||
"meshline": "^3.1.6",
|
||||
"react-composer": "^5.0.3",
|
||||
"stats-gl": "^2.0.0",
|
||||
"stats.js": "^0.17.0",
|
||||
"suspend-react": "^0.1.3",
|
||||
"three-mesh-bvh": "^0.7.0",
|
||||
"three-stdlib": "^2.29.9",
|
||||
"troika-three-text": "^0.49.0",
|
||||
"tunnel-rat": "^0.1.2",
|
||||
"utility-types": "^3.10.0",
|
||||
"uuid": "^9.0.1",
|
||||
"zustand": "^3.7.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-three/fiber": ">=8.0",
|
||||
"react": ">=18.0",
|
||||
"react-dom": ">=18.0",
|
||||
"three": ">=0.137"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@react-three/drei/node_modules/@monogrid/gainmap-js": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@monogrid/gainmap-js/-/gainmap-js-3.4.0.tgz",
|
||||
"integrity": "sha512-2Z0FATFHaoYJ8b+Y4y4Hgfn3FRFwuU5zRrk+9dFWp4uGAdHGqVEdP7HP+gLA3X469KXHmfupJaUbKo1b/aDKIg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"promise-worker-transferable": "^1.0.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"three": ">= 0.159.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-three/fiber": {
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.18.0.tgz",
|
||||
|
|
@ -5760,6 +5895,12 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/draco3d": {
|
||||
"version": "1.4.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.10.tgz",
|
||||
"integrity": "sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||
|
|
@ -5919,6 +6060,12 @@
|
|||
"integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/offscreencanvas": {
|
||||
"version": "2019.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz",
|
||||
"integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
|
||||
|
|
@ -6388,6 +6535,24 @@
|
|||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@use-gesture/core": {
|
||||
"version": "10.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz",
|
||||
"integrity": "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@use-gesture/react": {
|
||||
"version": "10.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@use-gesture/react/-/react-10.3.1.tgz",
|
||||
"integrity": "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@use-gesture/core": "10.3.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">= 16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vis.gl/react-mapbox": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vis.gl/react-mapbox/-/react-mapbox-8.1.0.tgz",
|
||||
|
|
@ -7177,6 +7342,15 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/camera-controls": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/camera-controls/-/camera-controls-2.10.1.tgz",
|
||||
"integrity": "sha512-KnaKdcvkBJ1Irbrzl8XD6WtZltkRjp869Jx8c0ujs9K+9WD+1D7ryBsCiVqJYUqt6i/HR5FxT7RLASieUD+Q5w==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"three": ">=0.126.1"
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001770",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001770.tgz",
|
||||
|
|
@ -7417,11 +7591,28 @@
|
|||
"integrity": "sha512-aNWR3te65YiaVFu/iwdqOo3cyUBZHUheE4d6EtgQu/T18jh/9SpoYXjXF/OzUD3Cqy0pGryoqtuy5gxD8tqX9Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cross-env": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
|
||||
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"cross-env": "src/bin/cross-env.js",
|
||||
"cross-env-shell": "src/bin/cross-env-shell.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.14",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
|
|
@ -7921,6 +8112,15 @@
|
|||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-gpu": {
|
||||
"version": "5.0.70",
|
||||
"resolved": "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.70.tgz",
|
||||
"integrity": "sha512-bqerEP1Ese6nt3rFkwPnGbsUF9a4q+gMmpTVVOEzoCyeCc+y7/RvJnQZJx1JwhgQI5Ntg0Kgat8Uu7XpBqnz1w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"webgl-constants": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/dfa": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz",
|
||||
|
|
@ -7955,6 +8155,12 @@
|
|||
"url": "https://github.com/sponsors/panva"
|
||||
}
|
||||
},
|
||||
"node_modules/draco3d": {
|
||||
"version": "1.5.7",
|
||||
"resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.7.tgz",
|
||||
"integrity": "sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
|
|
@ -9099,6 +9305,12 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/glsl-noise": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/glsl-noise/-/glsl-noise-0.0.0.tgz",
|
||||
"integrity": "sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/goober": {
|
||||
"version": "2.1.18",
|
||||
"resolved": "https://registry.npmjs.org/goober/-/goober-2.1.18.tgz",
|
||||
|
|
@ -9258,6 +9470,12 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/hls.js": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.3.5.tgz",
|
||||
"integrity": "sha512-uybAvKS6uDe0MnWNEPnO0krWVr+8m2R0hJ/viql8H3MVK+itq8gGQuIYoFHL3rECkIpNH98Lw8YuuWMKZxp3Ew==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/hoist-non-react-statics": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
||||
|
|
@ -9386,6 +9604,12 @@
|
|||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/immediate": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/import-fresh": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
||||
|
|
@ -9761,6 +9985,12 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-promise": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
|
||||
"integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-regex": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
|
||||
|
|
@ -9946,7 +10176,6 @@
|
|||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/isobject": {
|
||||
|
|
@ -10309,6 +10538,15 @@
|
|||
"integrity": "sha512-rDU6bkpuMs8YRt/UpkuYEAsYSoNuDEbrE41I3KNvmXREGH6DGBJ8Wbak4by29wNOQ27zk4g4HL82zf0OGhwRuw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lie": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
||||
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"immediate": "~3.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/linebreak": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz",
|
||||
|
|
@ -10456,6 +10694,16 @@
|
|||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/maath": {
|
||||
"version": "0.10.8",
|
||||
"resolved": "https://registry.npmjs.org/maath/-/maath-0.10.8.tgz",
|
||||
"integrity": "sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/three": ">=0.134.0",
|
||||
"three": ">=0.134.0"
|
||||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.21",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
||||
|
|
@ -10600,6 +10848,15 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/meshline": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/meshline/-/meshline-3.3.1.tgz",
|
||||
"integrity": "sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"three": ">=0.137"
|
||||
}
|
||||
},
|
||||
"node_modules/meshoptimizer": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.0.1.tgz",
|
||||
|
|
@ -11137,7 +11394,6 @@
|
|||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
|
|
@ -11378,6 +11634,16 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/promise-worker-transferable": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/promise-worker-transferable/-/promise-worker-transferable-1.0.4.tgz",
|
||||
"integrity": "sha512-bN+0ehEnrXfxV2ZQvU2PetO0n4gqBD4ulq3MI1WOPLgr7/Mg9yRQkX5+0v1vagr74ZTsl7XtzlaYDo2EuCeYJw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"is-promise": "^2.1.0",
|
||||
"lie": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/prop-types": {
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
|
|
@ -11585,6 +11851,18 @@
|
|||
"react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/react-composer": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/react-composer/-/react-composer-5.0.3.tgz",
|
||||
"integrity": "sha512-1uWd07EME6XZvMfapwZmc7NgCZqDemcvicRi3wMJzXsQLvZ3L7fTHVyPy1bZdnWXM4iPjYuNE+uJ41MLKeTtnA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-day-picker": {
|
||||
"version": "9.13.2",
|
||||
"resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.13.2.tgz",
|
||||
|
|
@ -12635,7 +12913,6 @@
|
|||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
|
|
@ -12648,7 +12925,6 @@
|
|||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
|
|
@ -12973,6 +13249,32 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/stats-gl": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/stats-gl/-/stats-gl-2.4.2.tgz",
|
||||
"integrity": "sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/three": "*",
|
||||
"three": "^0.170.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/three": "*",
|
||||
"three": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/stats-gl/node_modules/three": {
|
||||
"version": "0.170.0",
|
||||
"resolved": "https://registry.npmjs.org/three/-/three-0.170.0.tgz",
|
||||
"integrity": "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/stats.js": {
|
||||
"version": "0.17.0",
|
||||
"resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz",
|
||||
"integrity": "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/std-env": {
|
||||
"version": "3.10.0",
|
||||
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
|
||||
|
|
@ -13313,11 +13615,49 @@
|
|||
}
|
||||
},
|
||||
"node_modules/three": {
|
||||
"version": "0.183.2",
|
||||
"resolved": "https://registry.npmjs.org/three/-/three-0.183.2.tgz",
|
||||
"integrity": "sha512-di3BsL2FEQ1PA7Hcvn4fyJOlxRRgFYBpMTcyOgkwJIaDOdJMebEFPA+t98EvjuljDx4hNulAGwF6KIjtwI5jgQ==",
|
||||
"version": "0.152.2",
|
||||
"resolved": "https://registry.npmjs.org/three/-/three-0.152.2.tgz",
|
||||
"integrity": "sha512-Ff9zIpSfkkqcBcpdiFo2f35vA9ZucO+N8TNacJOqaEE6DrB0eufItVMib8bK8Pcju/ZNT6a7blE1GhTpkdsILw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/three-mesh-bvh": {
|
||||
"version": "0.7.6",
|
||||
"resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.7.6.tgz",
|
||||
"integrity": "sha512-rCjsnxEqR9r1/C/lCqzGLS67NDty/S/eT6rAJfDvsanrIctTWdNoR4ZOGWewCB13h1QkVo2BpmC0wakj1+0m8A==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"three": ">= 0.151.0"
|
||||
}
|
||||
},
|
||||
"node_modules/three-stdlib": {
|
||||
"version": "2.36.1",
|
||||
"resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.36.1.tgz",
|
||||
"integrity": "sha512-XyGQrFmNQ5O/IoKm556ftwKsBg11TIb301MB5dWNicziQBEs2g3gtOYIf7pFiLa0zI2gUwhtCjv9fmjnxKZ1Cg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/draco3d": "^1.4.0",
|
||||
"@types/offscreencanvas": "^2019.6.4",
|
||||
"@types/webxr": "^0.5.2",
|
||||
"draco3d": "^1.4.1",
|
||||
"fflate": "^0.6.9",
|
||||
"potpack": "^1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"three": ">=0.128.0"
|
||||
}
|
||||
},
|
||||
"node_modules/three-stdlib/node_modules/fflate": {
|
||||
"version": "0.6.10",
|
||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz",
|
||||
"integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/three-stdlib/node_modules/potpack": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz",
|
||||
"integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/tiny-inflate": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
|
||||
|
|
@ -13460,6 +13800,36 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/troika-three-text": {
|
||||
"version": "0.49.1",
|
||||
"resolved": "https://registry.npmjs.org/troika-three-text/-/troika-three-text-0.49.1.tgz",
|
||||
"integrity": "sha512-lXGWxgjJP9kw4i4Wh+0k0Q/7cRfS6iOME4knKht/KozPu9GcFA9NnNpRvehIhrUawq9B0ZRw+0oiFHgRO+4Wig==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bidi-js": "^1.0.2",
|
||||
"troika-three-utils": "^0.49.0",
|
||||
"troika-worker-utils": "^0.49.0",
|
||||
"webgl-sdf-generator": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"three": ">=0.125.0"
|
||||
}
|
||||
},
|
||||
"node_modules/troika-three-utils": {
|
||||
"version": "0.49.0",
|
||||
"resolved": "https://registry.npmjs.org/troika-three-utils/-/troika-three-utils-0.49.0.tgz",
|
||||
"integrity": "sha512-umitFL4cT+Fm/uONmaQEq4oZlyRHWwVClaS6ZrdcueRvwc2w+cpNQ47LlJKJswpqtMFWbEhOLy0TekmcPZOdYA==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"three": ">=0.125.0"
|
||||
}
|
||||
},
|
||||
"node_modules/troika-worker-utils": {
|
||||
"version": "0.49.0",
|
||||
"resolved": "https://registry.npmjs.org/troika-worker-utils/-/troika-worker-utils-0.49.0.tgz",
|
||||
"integrity": "sha512-1xZHoJrG0HFfCvT/iyN41DvI/nRykiBtHqFkGaGgJwq5iXfIZFBiPPEHFpPpgyKM3Oo5ITHXP5wM2TNQszYdVg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ts-api-utils": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
|
||||
|
|
@ -13500,6 +13870,43 @@
|
|||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/tunnel-rat": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-rat/-/tunnel-rat-0.1.2.tgz",
|
||||
"integrity": "sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"zustand": "^4.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/tunnel-rat/node_modules/zustand": {
|
||||
"version": "4.5.7",
|
||||
"resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz",
|
||||
"integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"use-sync-external-store": "^1.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.7.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": ">=16.8",
|
||||
"immer": ">=9.0.6",
|
||||
"react": ">=16.8"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"immer": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
|
|
@ -13850,12 +14257,43 @@
|
|||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/use-sync-external-store": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
|
||||
"integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/utility-types": {
|
||||
"version": "3.11.0",
|
||||
"resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz",
|
||||
"integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/validate-npm-package-license": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||
|
|
@ -14890,6 +15328,17 @@
|
|||
"integrity": "sha512-VlLyZb9rb0Ir/NvC6T3YOcnftzUMg8hDYMb9xf1pzzM5z5wKogL6q1wZeqE5e+oHSw0CVcTFtYCbSa1ZEwnDZQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/webgl-constants": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/webgl-constants/-/webgl-constants-1.1.1.tgz",
|
||||
"integrity": "sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg=="
|
||||
},
|
||||
"node_modules/webgl-sdf-generator": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz",
|
||||
"integrity": "sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
|
|
@ -14916,7 +15365,6 @@
|
|||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
"@mui/styles": "^6.1.6",
|
||||
"@mui/x-date-pickers": "^7.26.0",
|
||||
"@react-pdf/renderer": "^4.3.0",
|
||||
"@react-three/drei": "^9.105.6",
|
||||
"@react-three/fiber": "^8.18.0",
|
||||
"@sentry/react": "^8.38.0",
|
||||
"@turf/area": "^7.2.0",
|
||||
|
|
@ -76,7 +77,7 @@
|
|||
"react-virtualized-auto-sizer": "^1.0.25",
|
||||
"recharts": "^2.15.1",
|
||||
"semver": "^7.7.1",
|
||||
"three": "^0.183.2",
|
||||
"three": "^0.152.2",
|
||||
"victory": "^37.3.6",
|
||||
"weather-icons-react": "^1.2.0"
|
||||
},
|
||||
|
|
|
|||
43
src/3dModels/Shapes/3D/Sphere.tsx
Normal file
43
src/3dModels/Shapes/3D/Sphere.tsx
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import { useMemo } from "react";
|
||||
import * as THREE from "three";
|
||||
import BaseMesh, { BaseMeshProps } from "../BaseMesh";
|
||||
|
||||
export interface SphereGeometry {
|
||||
radius: number
|
||||
widthSegments?: number
|
||||
heightSegments?: number
|
||||
phiStart?: number
|
||||
phiLength?: number
|
||||
thetaStart?: number
|
||||
thetaLength?: number
|
||||
}
|
||||
|
||||
interface Props extends Omit<BaseMeshProps, "geometry"> {
|
||||
geometry: SphereGeometry;
|
||||
}
|
||||
|
||||
export default function Sphere(props: Props){
|
||||
const { geometry } = props;
|
||||
|
||||
const geo = useMemo(() => {
|
||||
return new THREE.SphereGeometry(
|
||||
geometry.radius,
|
||||
geometry.widthSegments,
|
||||
geometry.heightSegments,
|
||||
geometry.phiStart,
|
||||
geometry.phiLength,
|
||||
geometry.thetaStart,
|
||||
geometry.thetaLength
|
||||
);
|
||||
}, [
|
||||
geometry.radius,
|
||||
geometry.widthSegments,
|
||||
geometry.heightSegments,
|
||||
geometry.phiStart,
|
||||
geometry.phiLength,
|
||||
geometry.thetaStart,
|
||||
geometry.thetaLength
|
||||
]);
|
||||
|
||||
return <BaseMesh {...props} geometry={geo} />;
|
||||
}
|
||||
|
|
@ -2,7 +2,8 @@ import OrbitCameraControls from "3dModels/CameraControls/OrbitCameraControls";
|
|||
import { Canvas } from "@react-three/fiber";
|
||||
import { Bin } from "models";
|
||||
import BinShell from "./BinParts/BinShell";
|
||||
import GrainFillFlat from "./grainFill/GrainFillFlat";
|
||||
import GrainFillFlat from "./BinInventory/GrainFillFlat";
|
||||
import BinCables from "./BinCables/BinCables";
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
|
|
@ -53,8 +54,9 @@ export default function Bin3dView(props: Props){
|
|||
fillPercent={fillPercent}
|
||||
/>
|
||||
)}
|
||||
</group>
|
||||
{/* cables */}
|
||||
<BinCables bin={bin}/>
|
||||
</group>
|
||||
|
||||
{/* lighting */}
|
||||
<ambientLight intensity={0.2} color={"white"}/>
|
||||
|
|
@ -62,12 +64,6 @@ export default function Bin3dView(props: Props){
|
|||
<directionalLight intensity={0.2} color={"white"} position={[0,0,-5]}/>
|
||||
<directionalLight intensity={0.2} color={"white"} position={[5,0,0]}/>
|
||||
<directionalLight intensity={0.2} color={"white"} position={[-5,0,0]}/>
|
||||
{/* <hemisphereLight
|
||||
color={"white"}
|
||||
groundColor={"#444"}
|
||||
intensity={0.7}
|
||||
/> */}
|
||||
{/* camera controls */}
|
||||
<OrbitCameraControls clampVerticalRotation />
|
||||
</Canvas>
|
||||
)
|
||||
|
|
|
|||
200
src/bin/3dView/BinCables/BinCables.tsx
Normal file
200
src/bin/3dView/BinCables/BinCables.tsx
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
import GrainCable, { CableData } from "./GrainCable";
|
||||
import { avg } from "utils";
|
||||
import { Vector3 } from "three";
|
||||
import { useMemo } from "react";
|
||||
import { Bin } from "models";
|
||||
import React from "react";
|
||||
|
||||
interface CableOrbit {
|
||||
orbit: number;
|
||||
radius: number; // in cm
|
||||
expectedCount: number;
|
||||
assignedCount?: number;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
bin: Bin
|
||||
}
|
||||
|
||||
export default function BinCables(props: Props){
|
||||
const {bin} = props
|
||||
const getLayoutFromDiameter = (diameterCm: number): CableOrbit[] => {
|
||||
const diameterFt = diameterCm / 30.48;
|
||||
|
||||
let summaries: { Orbit: number; DistanceFromCenter: number; NumberOfCables: number }[] = [];
|
||||
|
||||
if (diameterFt < 24) {
|
||||
summaries.push({ Orbit: 0, DistanceFromCenter: 2, NumberOfCables: 1 });
|
||||
} else if (diameterFt < 36) {
|
||||
summaries.push({ Orbit: 1, DistanceFromCenter: 7, NumberOfCables: 3 });
|
||||
} else if (diameterFt < 42) {
|
||||
summaries.push({ Orbit: 0, DistanceFromCenter: 2, NumberOfCables: 1 });
|
||||
summaries.push({ Orbit: 1, DistanceFromCenter: 9, NumberOfCables: 3 });
|
||||
} else if (diameterFt < 48) {
|
||||
summaries.push({ Orbit: 0, DistanceFromCenter: 2, NumberOfCables: 1 });
|
||||
summaries.push({ Orbit: 1, DistanceFromCenter: 14, NumberOfCables: 4 });
|
||||
} else if (diameterFt < 54) {
|
||||
summaries.push({ Orbit: 0, DistanceFromCenter: 2, NumberOfCables: 1 });
|
||||
summaries.push({ Orbit: 1, DistanceFromCenter: 16, NumberOfCables: 5 });
|
||||
} else if (diameterFt < 60) {
|
||||
summaries.push({ Orbit: 0, DistanceFromCenter: 2, NumberOfCables: 1 });
|
||||
summaries.push({ Orbit: 1, DistanceFromCenter: 18, NumberOfCables: 6 });
|
||||
} else if (diameterFt < 72) {
|
||||
summaries.push({ Orbit: 0, DistanceFromCenter: 2, NumberOfCables: 1 });
|
||||
summaries.push({ Orbit: 1, DistanceFromCenter: 20, NumberOfCables: 7 });
|
||||
} else if (diameterFt < 78) {
|
||||
summaries.push({ Orbit: 1, DistanceFromCenter: 10, NumberOfCables: 4 });
|
||||
summaries.push({ Orbit: 2, DistanceFromCenter: 27, NumberOfCables: 9 });
|
||||
} else if (diameterFt < 90) {
|
||||
summaries.push({ Orbit: 1, DistanceFromCenter: 10, NumberOfCables: 4 });
|
||||
summaries.push({ Orbit: 2, DistanceFromCenter: 29, NumberOfCables: 10 });
|
||||
} else if (diameterFt < 105) {
|
||||
summaries.push({ Orbit: 0, DistanceFromCenter: 2, NumberOfCables: 1 });
|
||||
summaries.push({ Orbit: 1, DistanceFromCenter: 18, NumberOfCables: 6 });
|
||||
summaries.push({ Orbit: 2, DistanceFromCenter: 36, NumberOfCables: 12 });
|
||||
} else {
|
||||
summaries.push({ Orbit: 1, DistanceFromCenter: 9, NumberOfCables: 3 });
|
||||
summaries.push({ Orbit: 2, DistanceFromCenter: 26.5, NumberOfCables: 9 });
|
||||
summaries.push({ Orbit: 3, DistanceFromCenter: 44, NumberOfCables: 14 });
|
||||
}
|
||||
|
||||
return summaries.map(s => ({
|
||||
orbit: s.Orbit,
|
||||
radius: s.DistanceFromCenter * 30.48, // ft → cm
|
||||
expectedCount: s.NumberOfCables
|
||||
}));
|
||||
};
|
||||
|
||||
const distributeCables = (cableCount: number, layout: CableOrbit[]) => {
|
||||
const totalExpected = layout.reduce((sum, o) => sum + o.expectedCount, 0);
|
||||
|
||||
let assigned = layout.map(o => ({
|
||||
...o,
|
||||
assignedCount: Math.round((o.expectedCount / totalExpected) * cableCount)
|
||||
}));
|
||||
|
||||
// normalize rounding
|
||||
let currentTotal = assigned.reduce((sum, o) => sum + (o.assignedCount ?? 0), 0);
|
||||
|
||||
while (currentTotal < cableCount) {
|
||||
assigned[assigned.length - 1].assignedCount!++;
|
||||
currentTotal++;
|
||||
}
|
||||
|
||||
while (currentTotal > cableCount) {
|
||||
assigned[assigned.length - 1].assignedCount!--;
|
||||
currentTotal--;
|
||||
}
|
||||
|
||||
return assigned;
|
||||
};
|
||||
|
||||
const getTopY = (radiusFromCenter: number) => {
|
||||
const binRadius = bin.diameter() / 2;
|
||||
|
||||
const distanceFromEdge = binRadius - radiusFromCenter;
|
||||
|
||||
const angleRad = bin.roofAngle() * (Math.PI / 180);
|
||||
|
||||
const roofRise = Math.tan(angleRad) * distanceFromEdge;
|
||||
|
||||
return bin.sidewallHeight() / 2 + roofRise;
|
||||
};
|
||||
|
||||
const getBottomY = (radiusFromCenter: number) => {
|
||||
const binRadius = bin.diameter() / 2;
|
||||
|
||||
const distanceFromCenter = binRadius - radiusFromCenter;
|
||||
|
||||
const angleRad = bin.hopperAngle() * (Math.PI / 180);
|
||||
|
||||
const hopperDrop = Math.tan(angleRad) * distanceFromCenter;
|
||||
|
||||
const clearance = 60 //this is in cm
|
||||
|
||||
return -bin.sidewallHeight() / 2 - hopperDrop + clearance;
|
||||
};
|
||||
|
||||
const buildCablePositions = (bin: Bin): CableData[] => {
|
||||
const cables = [...(bin.status.grainCables ?? [])];
|
||||
|
||||
if (cables.length === 0) return [];
|
||||
|
||||
// optional: sort cables (better visual consistency later)
|
||||
//cables.sort((a, b) => b.celcius.length - a.celcius.length);
|
||||
cables.sort((a, b) => {
|
||||
//if the cables have the same number of nodes
|
||||
if (b.celcius.length === a.celcius.length) {
|
||||
//sort by temp only last and any type that has humidity first
|
||||
if ((avg(a.relativeHumidity) === 0) && (avg(b.relativeHumidity) !== 0)) {
|
||||
return 1;
|
||||
} else if ((avg(b.relativeHumidity) === 0) && (avg(a.relativeHumidity) !== 0)) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return a.key > b.key ? 1 : -1;
|
||||
}
|
||||
}
|
||||
//otherwise sort by the longest cable first
|
||||
return b.celcius.length - a.celcius.length;
|
||||
});
|
||||
|
||||
const layout = getLayoutFromDiameter(bin.diameter());
|
||||
const distributed = distributeCables(cables.length, layout);
|
||||
|
||||
|
||||
const cableRadius = 5;
|
||||
|
||||
const result: CableData[] = [];
|
||||
|
||||
let cableIndex = 0;
|
||||
|
||||
distributed.forEach(orbit => {
|
||||
const count = orbit.assignedCount ?? 0;
|
||||
|
||||
const topY = getTopY(orbit.radius)
|
||||
const bottomY = getBottomY(orbit.radius)
|
||||
|
||||
if (orbit.orbit === 0 && count > 0) {
|
||||
const cable = cables[cableIndex++];
|
||||
|
||||
result.push({
|
||||
radius: cableRadius,
|
||||
topPosition: new Vector3(0, topY, 0),
|
||||
bottomPosition: new Vector3(0, bottomY, 0),
|
||||
grainCable: cable
|
||||
// optionally attach cable data later
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const angle = (i / count) * Math.PI * 2;
|
||||
const x = Math.cos(angle) * orbit.radius;
|
||||
const z = Math.sin(angle) * orbit.radius;
|
||||
const cable = cables[cableIndex++];
|
||||
|
||||
result.push({
|
||||
radius: cableRadius,
|
||||
topPosition: new Vector3(x,topY,z),
|
||||
bottomPosition: new Vector3(x,bottomY,z),
|
||||
grainCable: cable
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const cables3D = useMemo(() => {
|
||||
return buildCablePositions(bin);
|
||||
}, [bin]);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{cables3D.map(cable => (
|
||||
<GrainCable cable={cable}/>
|
||||
))}
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
110
src/bin/3dView/BinCables/CableNode.tsx
Normal file
110
src/bin/3dView/BinCables/CableNode.tsx
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
import Sphere, { SphereGeometry } from "3dModels/Shapes/3D/Sphere"
|
||||
import { useFrame, useThree } from "@react-three/fiber"
|
||||
import { Billboard, Text } from "@react-three/drei"
|
||||
import React, { useMemo, useState } from "react"
|
||||
import { Vector3 } from "three"
|
||||
import { cloneDeep } from "lodash"
|
||||
import { describeMeasurement } from "pbHelpers/MeasurementDescriber"
|
||||
import { quack } from "protobuf-ts/quack"
|
||||
|
||||
export interface NodeData {
|
||||
radius: number
|
||||
position: Vector3
|
||||
celcius: number
|
||||
humidity?: number
|
||||
moisture?: number
|
||||
topNode?: boolean
|
||||
}
|
||||
|
||||
interface Props {
|
||||
node: NodeData
|
||||
}
|
||||
|
||||
export default function CableNode(props: Props){
|
||||
const {node} = props
|
||||
const { camera } = useThree();
|
||||
const [showLabel, setShowLabel] = useState(false);
|
||||
|
||||
useFrame(() => {
|
||||
//use the cameras distance to the center of the bin
|
||||
const distance = camera.position.distanceTo(new Vector3(0, 0, 0))
|
||||
console.log(distance)
|
||||
|
||||
const SHOW_DISTANCE = 15;
|
||||
const HIDE_DISTANCE = 16; // hysteresis buffer
|
||||
|
||||
if (!showLabel && distance < SHOW_DISTANCE) {
|
||||
setShowLabel(true);
|
||||
} else if (showLabel && distance > HIDE_DISTANCE) {
|
||||
setShowLabel(false);
|
||||
}
|
||||
});
|
||||
|
||||
const geometry = React.useMemo(() => ({
|
||||
radius: node.radius,
|
||||
} as SphereGeometry), [node]);
|
||||
|
||||
const labelPosition = node.position.clone();
|
||||
|
||||
const dir = camera.position.clone().sub(node.position).normalize();
|
||||
|
||||
// push label slightly toward camera
|
||||
labelPosition.add(dir.multiplyScalar(1)); // small offset like 0.5–2 units
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{!showLabel ?
|
||||
<Sphere geometry={geometry} position={node.position}/>
|
||||
:
|
||||
<Billboard position={labelPosition}>
|
||||
<group renderOrder={999}>
|
||||
{/* Background */}
|
||||
<mesh position={[0, 0, -1]}>
|
||||
<planeGeometry args={[200, 100]} />
|
||||
<meshBasicMaterial
|
||||
color="black"
|
||||
transparent
|
||||
opacity={0.7}
|
||||
depthWrite={false}
|
||||
depthTest={false}
|
||||
/>
|
||||
</mesh>
|
||||
|
||||
{/* Temp Text */}
|
||||
<Text
|
||||
position={[0, 35, 0]}
|
||||
fontSize={30}
|
||||
color={describeMeasurement(quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE).colour()}
|
||||
anchorX="center"
|
||||
anchorY="middle">
|
||||
{node.celcius.toFixed(2)}°C
|
||||
</Text>
|
||||
{/* Humidity Text */}
|
||||
{node.humidity &&
|
||||
<Text
|
||||
position={[0, 0, 0]}
|
||||
fontSize={30}
|
||||
color={describeMeasurement(quack.MeasurementType.MEASUREMENT_TYPE_PERCENT).colour()}
|
||||
anchorX="center"
|
||||
anchorY="middle">
|
||||
{node.humidity.toFixed(2)}%
|
||||
</Text>
|
||||
}
|
||||
{/* Moisture Text */}
|
||||
{node.moisture &&
|
||||
<Text
|
||||
position={[0, -35, 0]}
|
||||
fontSize={30}
|
||||
color={describeMeasurement(quack.MeasurementType.MEASUREMENT_TYPE_GRAIN_EMC).colour()}
|
||||
anchorX="center"
|
||||
anchorY="middle">
|
||||
{node.moisture.toFixed(2)}% EMC
|
||||
</Text>
|
||||
}
|
||||
</group>
|
||||
</Billboard>
|
||||
}
|
||||
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
86
src/bin/3dView/BinCables/GrainCable.tsx
Normal file
86
src/bin/3dView/BinCables/GrainCable.tsx
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import Cylinder, { CylinderGeometry } from "3dModels/Shapes/3D/Cylinder"
|
||||
import { pond } from "protobuf-ts/pond"
|
||||
import React from "react"
|
||||
import { Vector3 } from "three"
|
||||
import CableNode, { NodeData } from "./CableNode"
|
||||
|
||||
export interface CableData {
|
||||
radius: number
|
||||
topPosition: Vector3
|
||||
bottomPosition: Vector3
|
||||
grainCable: pond.GrainCable
|
||||
radialSegments?: number
|
||||
heightSegments?: number
|
||||
}
|
||||
|
||||
interface Props {
|
||||
cable: CableData
|
||||
}
|
||||
export default function GrainCable(props: Props) {
|
||||
const {cable} = props
|
||||
|
||||
const calculateHeight = () => {
|
||||
return cable.topPosition.distanceTo(cable.bottomPosition)
|
||||
}
|
||||
|
||||
const calculateCenter = () => {
|
||||
return cable.bottomPosition.clone()
|
||||
.add(
|
||||
cable.topPosition.clone()
|
||||
.sub(cable.bottomPosition)
|
||||
.multiplyScalar(0.5)
|
||||
);
|
||||
};
|
||||
|
||||
const buildCableNodes = () => {
|
||||
const nodeRadius = 20
|
||||
const grainCable = cable.grainCable
|
||||
|
||||
const nodeCount = grainCable.celcius.length;
|
||||
|
||||
if (nodeCount === 0) return [];
|
||||
|
||||
const bottomY = cable.bottomPosition.y;
|
||||
const topY = cable.topPosition.y;
|
||||
const height = topY - bottomY;
|
||||
|
||||
const spacing = height / nodeCount;
|
||||
|
||||
let nodeData: NodeData[] = []
|
||||
grainCable.celcius.forEach((celcius,i) => {
|
||||
const nodeY = bottomY + (i * spacing);
|
||||
|
||||
const humidity = grainCable.relativeHumidity[i] || undefined;
|
||||
const moisture = grainCable.moisture[i] || undefined;
|
||||
|
||||
nodeData.push({
|
||||
radius: nodeRadius,
|
||||
position: new Vector3(cable.bottomPosition.x, nodeY, cable.bottomPosition.z),
|
||||
celcius: celcius,
|
||||
humidity: humidity,
|
||||
moisture: moisture,
|
||||
topNode: grainCable.topNode === i
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
return nodeData
|
||||
}
|
||||
|
||||
const geometry = React.useMemo(() => ({
|
||||
radiusTop: cable.radius,
|
||||
radiusBottom: cable.radius,
|
||||
height: calculateHeight(),
|
||||
radialSegments: cable.radialSegments ?? 10,
|
||||
heightSegments: cable.heightSegments ?? 2
|
||||
} as CylinderGeometry), [cable]);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Cylinder geometry={geometry} position={calculateCenter()} opacity={0.5}/>
|
||||
{buildCableNodes().map(node => (
|
||||
<CableNode node={node}/>
|
||||
))}
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
|
@ -72,6 +72,14 @@ export class Bin {
|
|||
return this.settings.specs?.advancedDimensions?.hopperHeight ?? 0;
|
||||
}
|
||||
|
||||
public roofAngle() : number {
|
||||
return this.settings.specs?.advancedDimensions?.roofAngle ?? 0;
|
||||
}
|
||||
|
||||
public hopperAngle() : number {
|
||||
return this.settings.specs?.advancedDimensions?.hopperAngle ?? 0;
|
||||
}
|
||||
|
||||
public key(): string {
|
||||
return this.settings.key;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue