diff --git a/examples/yarn.lock b/examples/yarn.lock index 86d527108fa..21ce2261616 100644 --- a/examples/yarn.lock +++ b/examples/yarn.lock @@ -175,26 +175,23 @@ commander "^2.15.1" "@cognite/reveal@link:../viewer": - version "4.10.8" - dependencies: - "@rajesh896/broprint.js" "^2.1.1" - "@tweenjs/tween.js" "19.0.0" - assert "2.1.0" - async-mutex "0.4.1" - glslify "7.1.1" - glslify-import "3.1.0" - html2canvas "^1.4.1" - lodash "4.17.21" - loglevel "1.9.1" - mixpanel-browser "2.49.0" - path-browserify "1.0.1" - random-seed "0.3.0" - rxjs "7.8.1" - skmeans "0.11.3" - sparse-octree "7.1.8" + version "0.0.0" + uid "" + +"@cognite/sdk-core@^4.9.0": + version "4.10.1" + resolved "https://registry.yarnpkg.com/@cognite/sdk-core/-/sdk-core-4.10.1.tgz#be33429bc57ae371d2b8a8b1e1e542a103d33610" + integrity sha512-X0chZgfwRZoXdv3iPnWY7ClfRbHkKUCjeLsYrtWJV2J8kbvy54Hwd5U50tZ83VjKpwolMOktB9pteiTRkJj9ag== + dependencies: + cross-fetch "^3.0.4" + is-buffer "^2.0.5" + lodash "^4.17.11" + query-string "^5.1.1" + url "^0.11.0" "@cognite/sdk@link:../viewer/node_modules/@cognite/sdk": version "0.0.0" + uid "" "@discoveryjs/json-ext@^0.5.0": version "0.5.7" @@ -404,6 +401,11 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/geojson@^7946.0.8": + version "7946.0.14" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613" + integrity sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg== + "@types/hoist-non-react-statics@*": version "3.3.1" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" @@ -1021,6 +1023,17 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + camel-case@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" @@ -1216,6 +1229,13 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +cross-fetch@^3.0.4: + version "3.1.8" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== + dependencies: + node-fetch "^2.6.12" + cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -1336,6 +1356,15 @@ default-gateway@^6.0.3: dependencies: execa "^5.0.0" +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" @@ -1534,6 +1563,18 @@ es-abstract@^1.19.0, es-abstract@^1.19.5, es-abstract@^1.20.0: string.prototype.trimstart "^1.0.5" unbox-primitive "^1.0.2" +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + es-module-lexer@^0.9.0: version "0.9.3" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" @@ -1795,6 +1836,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + function.prototype.name@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" @@ -1810,6 +1856,11 @@ functions-have-names@^1.2.2: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +geojson@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/geojson/-/geojson-0.5.0.tgz#3cd6c96399be65b56ee55596116fe9191ce701c0" + integrity sha512-/Bx5lEn+qRF4TfQ5aLu6NH+UKtvIv7Lhc487y/c8BdludrCTpiWf9wyI0RTyqg49MFefIAvFDuEi5Dfd/zgNxQ== + get-intrinsic@^1.0.2: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" @@ -1828,6 +1879,17 @@ get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.2: has "^1.0.3" has-symbols "^1.0.3" +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + get-stream@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" @@ -2006,6 +2068,13 @@ glslify@7.1.1: through2 "^2.0.1" xtend "^4.0.0" +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" @@ -2038,6 +2107,18 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + has-symbols@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" @@ -2062,6 +2143,13 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -2294,6 +2382,11 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-buffer@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.4: version "1.2.6" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.6.tgz#fd6170b0b8c7e2cc73de342ef8284a2202023c44" @@ -2545,7 +2638,7 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21: +lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -2733,6 +2826,13 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" +node-fetch@^2.6.12: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-forge@^1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -2762,11 +2862,21 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + object-inspect@^1.12.2: version "1.12.2" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== +object-inspect@^1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + object-inspect@^1.9.0: version "1.11.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" @@ -3045,6 +3155,11 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -3057,6 +3172,22 @@ qs@6.10.3: dependencies: side-channel "^1.0.4" +qs@^6.11.2: + version "6.12.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.0.tgz#edd40c3b823995946a8a0b1f208669c7a200db77" + integrity sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg== + dependencies: + side-channel "^1.0.6" + +query-string@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + random-seed@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/random-seed/-/random-seed-0.3.0.tgz#d945f2e1f38f49e8d58913431b8bf6bb937556cd" @@ -3359,6 +3490,18 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" @@ -3412,6 +3555,16 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + signal-exit@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" @@ -3517,6 +3670,11 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== + string.prototype.trimend@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" @@ -3691,6 +3849,11 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + ts-loader@9.4.4: version "9.4.4" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.4.4.tgz#6ceaf4d58dcc6979f84125335904920884b7cee4" @@ -3753,6 +3916,14 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +url@^0.11.0: + version "0.11.3" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.3.tgz#6f495f4b935de40ce4a0a52faee8954244f3d3ad" + integrity sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw== + dependencies: + punycode "^1.4.1" + qs "^6.11.2" + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -3811,6 +3982,11 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + webpack-cli@^4.10.0: version "4.10.0" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" @@ -3942,6 +4118,14 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" diff --git a/viewer/package.json b/viewer/package.json index 4972513a203..835a701b96e 100644 --- a/viewer/package.json +++ b/viewer/package.json @@ -1,6 +1,6 @@ { "name": "@cognite/reveal", - "version": "4.10.8", + "version": "4.11.0", "description": "WebGL based 3D viewer for CAD and point clouds processed in Cognite Data Fusion.", "homepage": "https://github.com/cognitedata/reveal/tree/master/viewer", "repository": { diff --git a/viewer/packages/360-images/src/Image360Facade.ts b/viewer/packages/360-images/src/Image360Facade.ts index 64232a6b759..21684ec412f 100644 --- a/viewer/packages/360-images/src/Image360Facade.ts +++ b/viewer/packages/360-images/src/Image360Facade.ts @@ -115,19 +115,29 @@ export class Image360Facade { } public intersect(coords: THREE.Vector2, camera: THREE.Camera): Image360Entity | undefined { - this._rayCaster.setFromCamera(coords, camera); const cameraDirection = camera.getWorldDirection(new THREE.Vector3()); const cameraPosition = camera.position.clone(); - - const intersections = this._image360Collections - .flatMap(getImage360Entities) - .filter(hasVisibleIcon) - .map(entity => getIntersection(entity, this._rayCaster.ray)) - .filter(hasIntersection) - .map(intersectionToCameraSpace) - .filter(isInFrontOfCamera) - .sort(byDistanceToCamera) - .map(selectEntity); + const collectionMatrix = new THREE.Matrix4(); + + const intersections = this._image360Collections.flatMap(collection => + getImage360Entities(collection) + .filter(hasVisibleIcon) + .map( + getIntersector( + getTransformedRay( + this._rayCaster, + coords, + camera, + getWorldToModelCollectionMatrix(collection, collectionMatrix) + ) + ) + ) + .filter(hasIntersection) + .map(intersectionToCameraSpace) + .filter(isInFrontOfCamera) + .sort(byDistanceToCamera) + .map(selectEntity) + ); return first(intersections); @@ -139,8 +149,28 @@ export class Image360Facade { return entity.icon.getVisible() && !entity.image360Visualization.visible; } - function getIntersection(entity: Image360Entity, ray: THREE.Ray): [Image360Entity, THREE.Vector3 | null] { - return [entity, entity.icon.intersect(ray)]; + function getIntersector(ray: THREE.Ray): (entity: Image360Entity) => [Image360Entity, THREE.Vector3 | null] { + return (entity: Image360Entity) => [entity, entity.icon.intersect(ray)]; + } + + function getTransformedRay( + rayCaster: THREE.Raycaster, + coords: THREE.Vector2, + camera: THREE.Camera, + transform: THREE.Matrix4 + ): THREE.Ray { + rayCaster.setFromCamera(coords, camera); + rayCaster.ray.applyMatrix4(transform); + return rayCaster.ray; + } + + function getWorldToModelCollectionMatrix( + collection: DefaultImage360Collection, + collectionMatrix: THREE.Matrix4 + ): THREE.Matrix4 { + collection.getModelTransformation(collectionMatrix); + collectionMatrix.invert(); + return collectionMatrix; } function hasIntersection( diff --git a/viewer/packages/360-images/src/collection/DefaultImage360Collection.ts b/viewer/packages/360-images/src/collection/DefaultImage360Collection.ts index 72b4827b692..bf7515244b7 100644 --- a/viewer/packages/360-images/src/collection/DefaultImage360Collection.ts +++ b/viewer/packages/360-images/src/collection/DefaultImage360Collection.ts @@ -30,6 +30,7 @@ import { Image360AnnotationFilter } from '../annotation/Image360AnnotationFilter import { Image360 } from '../entity/Image360'; import { Image360Revision } from '../entity/Image360Revision'; import { ImageAssetLinkAnnotationInfo } from '@reveal/data-providers'; +import { Matrix4 } from 'three'; type Image360Events = 'image360Entered' | 'image360Exited'; @@ -64,6 +65,7 @@ export class DefaultImage360Collection implements Image360Collection { private _isCollectionVisible: boolean; private readonly _collectionId: string; private readonly _collectionLabel: string | undefined; + private readonly _setNeedsRedraw: () => void; get id(): string { return this._collectionId; @@ -101,7 +103,8 @@ export class DefaultImage360Collection implements Image360Collection { entities: Image360Entity[], icons: IconCollection, annotationFilter: Image360AnnotationFilter, - image360DataProvider: Image360DataProvider + image360DataProvider: Image360DataProvider, + setNeedsRedraw: () => void ) { this._collectionId = collectionId; this._collectionLabel = collectionLabel; @@ -110,6 +113,17 @@ export class DefaultImage360Collection implements Image360Collection { this._isCollectionVisible = true; this._annotationFilter = annotationFilter; this._image360DataProvider = image360DataProvider; + this._setNeedsRedraw = setNeedsRedraw; + } + + public getModelTransformation(out?: Matrix4): Matrix4 { + return this._icons.getTransform(out); + } + + public setModelTransformation(matrix: THREE.Matrix4): void { + this._icons.setTransform(matrix); + this.image360Entities.forEach(entity => entity.setWorldTransform(matrix)); + this._setNeedsRedraw(); } /** * Subscribes to events on 360 Image datasets. There are several event types: diff --git a/viewer/packages/360-images/src/collection/Image360Collection.ts b/viewer/packages/360-images/src/collection/Image360Collection.ts index a36ee755e7e..f0565c61f0c 100644 --- a/viewer/packages/360-images/src/collection/Image360Collection.ts +++ b/viewer/packages/360-images/src/collection/Image360Collection.ts @@ -10,6 +10,7 @@ import { Image360Revision } from '../entity/Image360Revision'; import { IdEither } from '@cognite/sdk'; import { Image360Annotation } from '../annotation/Image360Annotation'; import { ImageAssetLinkAnnotationInfo } from '@reveal/data-providers'; +import { Matrix4 } from 'three'; /** * Filter for finding annotations related to an asset @@ -84,6 +85,17 @@ export interface Image360Collection { */ targetRevisionDate: Date | undefined; + /** + * Sets the transformation matrix to be applied to the collection. + * @param matrix The transformation matrix to be applied to the collection. + */ + setModelTransformation(matrix: Matrix4): void; + + /** + * Gets the transformation matrix of the collection + */ + getModelTransformation(out?: Matrix4): Matrix4; + /** * Specify parameters used to determine the number of icons that are visible when entering 360 Images. * @param radius Only icons within the given radius will be made visible. diff --git a/viewer/packages/360-images/src/collection/Image360CollectionFactory.ts b/viewer/packages/360-images/src/collection/Image360CollectionFactory.ts index 9530584785f..978ac543913 100644 --- a/viewer/packages/360-images/src/collection/Image360CollectionFactory.ts +++ b/viewer/packages/360-images/src/collection/Image360CollectionFactory.ts @@ -22,11 +22,13 @@ export class Image360CollectionFactory { private readonly _onBeforeSceneRendered: EventTrigger; private readonly _iconsOptions: IconsOptions | undefined; private readonly _device: DeviceDescriptor; + private readonly _setNeedsRedraw: () => void; constructor( image360DataProvider: Image360Provider, sceneHandler: SceneHandler, onBeforeSceneRendered: EventTrigger, + setNeedsRedraw: () => void, device: DeviceDescriptor, iconsOptions?: IconsOptions ) { @@ -35,6 +37,7 @@ export class Image360CollectionFactory { this._onBeforeSceneRendered = onBeforeSceneRendered; this._iconsOptions = iconsOptions; this._device = device; + this._setNeedsRedraw = setNeedsRedraw; } public async create( @@ -86,7 +89,8 @@ export class Image360CollectionFactory { entities, collectionIcons, annotationFilterer, - this._image360DataProvider + this._image360DataProvider, + this._setNeedsRedraw ); function isDefined( diff --git a/viewer/packages/360-images/src/entity/Image360Entity.ts b/viewer/packages/360-images/src/entity/Image360Entity.ts index d19e3140cfe..08b4c823be6 100644 --- a/viewer/packages/360-images/src/entity/Image360Entity.ts +++ b/viewer/packages/360-images/src/entity/Image360Entity.ts @@ -12,14 +12,15 @@ import { Image360VisualizationBox } from './Image360VisualizationBox'; import { ImageAnnotationObject } from '../annotation/ImageAnnotationObject'; import { Overlay3DIcon } from '@reveal/3d-overlays'; import { Image360AnnotationFilter } from '../annotation/Image360AnnotationFilter'; -import { Color } from 'three'; +import { Color, Matrix4 } from 'three'; import cloneDeep from 'lodash/cloneDeep'; export class Image360Entity implements Image360 { private readonly _revisions: Image360RevisionEntity[]; private readonly _imageMetadata: Image360EventDescriptor; - private readonly _transform: THREE.Matrix4; + private readonly _modelTransform: THREE.Matrix4; + private readonly _worldTransform: THREE.Matrix4; private readonly _image360Icon: Overlay3DIcon; private readonly _image360VisualizationBox: Image360VisualizationBox; private _activeRevision: Image360RevisionEntity; @@ -31,7 +32,7 @@ export class Image360Entity implements Image360 { * @returns model-to-world transform of the 360 Image */ get transform(): THREE.Matrix4 { - return this._transform.clone(); + return this._worldTransform.clone(); } /** @@ -76,11 +77,12 @@ export class Image360Entity implements Image360 { icon: Overlay3DIcon, device: DeviceDescriptor ) { - this._transform = transform; + this._modelTransform = transform; + this._worldTransform = transform.clone(); this._image360Icon = icon; this._imageMetadata = image360Metadata; - this._image360VisualizationBox = new Image360VisualizationBox(this._transform, sceneHandler, device); + this._image360VisualizationBox = new Image360VisualizationBox(this._modelTransform, sceneHandler, device); this._image360VisualizationBox.visible = false; this._revisions = image360Metadata.imageRevisions.map( @@ -90,6 +92,11 @@ export class Image360Entity implements Image360 { this._activeRevision = this.getMostRecentRevision(); } + public setWorldTransform(matrix: Matrix4): void { + this._worldTransform.copy(matrix).multiply(this._modelTransform); + this._image360VisualizationBox.setWorldTransform(matrix); + } + /** * List all historical images for this entity. * @returns A list of available revisions. diff --git a/viewer/packages/360-images/src/entity/Image360VisualizationBox.ts b/viewer/packages/360-images/src/entity/Image360VisualizationBox.ts index 75020fda0df..8ef831359d6 100644 --- a/viewer/packages/360-images/src/entity/Image360VisualizationBox.ts +++ b/viewer/packages/360-images/src/entity/Image360VisualizationBox.ts @@ -27,6 +27,7 @@ export class Image360VisualizationBox implements Image360Visualization { private readonly _textureLoader: THREE.TextureLoader; private readonly _faceMaterialOrder: Image360Face['face'][] = ['left', 'right', 'top', 'bottom', 'front', 'back']; private readonly _annotationsGroup: THREE.Group = new THREE.Group(); + private readonly _localTransform: THREE.Matrix4; get opacity(): number { return this._visualizationState.opacity; @@ -84,7 +85,8 @@ export class Image360VisualizationBox implements Image360Visualization { } constructor(worldTransform: THREE.Matrix4, sceneHandler: SceneHandler, device: DeviceDescriptor) { - this._worldTransform = worldTransform; + this._localTransform = worldTransform.clone(); + this._worldTransform = worldTransform.clone(); this._sceneHandler = sceneHandler; this._device = device; this._textureLoader = new THREE.TextureLoader(); @@ -96,6 +98,15 @@ export class Image360VisualizationBox implements Image360Visualization { }; } + public setWorldTransform(matrix: THREE.Matrix4): void { + this._worldTransform.copy(matrix).multiply(this._localTransform); + + if (this._visualizationMesh) { + this._visualizationMesh.position.setFromMatrixPosition(this._worldTransform); + this._visualizationMesh.rotation.setFromRotationMatrix(this._worldTransform); + } + } + public loadImages(textures: Image360Texture[]): void { if (this._visualizationMesh) { this._faceMaterialOrder.forEach((face, index) => { @@ -118,7 +129,8 @@ export class Image360VisualizationBox implements Image360Visualization { const boxGeometry = new THREE.BoxGeometry(1, 1, 1); const visualizationMesh = new THREE.Mesh(boxGeometry, this._faceMaterials); visualizationMesh.renderOrder = this._visualizationState.renderOrder; - visualizationMesh.applyMatrix4(this._worldTransform); + visualizationMesh.position.setFromMatrixPosition(this._worldTransform); + visualizationMesh.rotation.setFromRotationMatrix(this._worldTransform); visualizationMesh.scale.copy(this._visualizationState.scale); visualizationMesh.visible = this._visualizationState.visible; visualizationMesh.add(this._annotationsGroup); diff --git a/viewer/packages/360-images/src/icons/IconCollection.ts b/viewer/packages/360-images/src/icons/IconCollection.ts index 155896ce6e8..a9f2ad3a0c9 100644 --- a/viewer/packages/360-images/src/icons/IconCollection.ts +++ b/viewer/packages/360-images/src/icons/IconCollection.ts @@ -108,13 +108,25 @@ export class IconCollection { sceneHandler.addObject3D(iconsSprites); } + public setTransform(transform: Matrix4): void { + this._pointsObject.setTransform(transform); + this._icons.forEach(icon => icon.setWorldTransform(transform)); + } + + public getTransform(out?: Matrix4): Matrix4 { + return this._pointsObject.getTransform(out); + } + private setIconClustersByLOD(octree: IconOctree, iconSprites: OverlayPointsObject): BeforeSceneRenderedDelegate { const projection = new Matrix4(); const frustum = new Frustum(); const screenSpaceAreaThreshold = 0.04; const minimumLevel = 3; return ({ camera }) => { - projection.copy(camera.projectionMatrix).multiply(camera.matrixWorldInverse); + projection + .copy(camera.projectionMatrix) + .multiply(camera.matrixWorldInverse) + .multiply(this._pointsObject.getTransform()); const nodesLOD = octree.getLODByScreenArea(screenSpaceAreaThreshold, projection, minimumLevel); frustum.setFromProjectionMatrix(projection); @@ -142,12 +154,18 @@ export class IconCollection { } private computeProximityPoints(octree: IconOctree, iconSprites: OverlayPointsObject): BeforeSceneRenderedDelegate { + const cameraModelSpacePosition = new Vector3(); + const worldTransform = new Matrix4(); return ({ camera }) => { + this._pointsObject.getTransform(worldTransform); + worldTransform.invert(); + cameraModelSpacePosition.copy(camera.position).applyMatrix4(worldTransform); + const points = this._proximityRadius === Infinity ? this._icons : octree - .findPoints(camera.position, this._proximityRadius) + .findPoints(cameraModelSpacePosition, this._proximityRadius) .map(pointContainer => { return pointContainer.data; }) @@ -156,7 +174,8 @@ export class IconCollection { const closestPoints = points .sort((a, b) => { return ( - a.getPosition().distanceToSquared(camera.position) - b.getPosition().distanceToSquared(camera.position) + a.getPosition().distanceToSquared(cameraModelSpacePosition) - + b.getPosition().distanceToSquared(cameraModelSpacePosition) ); }) .slice(0, this._proximityPointLimit + 1); //Add 1 to account for self. @@ -204,7 +223,7 @@ export class IconCollection { icons.forEach(icon => icon.on('selected', () => { - this._hoverSprite.position.copy(icon.getPosition()); + this._hoverSprite.position.copy(icon.getPosition().clone().applyMatrix4(this.getTransform())); this._hoverSprite.scale.set(icon.adaptiveScale * 2, icon.adaptiveScale * 2, 1); }) ); diff --git a/viewer/packages/360-images/unit-tests/Image360CollectionFactory.test.ts b/viewer/packages/360-images/unit-tests/Image360CollectionFactory.test.ts index 4f33e7eb9f9..578eb6e510f 100644 --- a/viewer/packages/360-images/unit-tests/Image360CollectionFactory.test.ts +++ b/viewer/packages/360-images/unit-tests/Image360CollectionFactory.test.ts @@ -60,6 +60,7 @@ describe(Image360CollectionFactory.name, () => { mock360ImageProvider.object(), mockSceneHandler.object(), new EventTrigger(), + () => {}, desktopDevice, { platformMaxPointsSize: 256 } ); diff --git a/viewer/packages/360-images/visual-tests/Image360.VisualTest.ts b/viewer/packages/360-images/visual-tests/Image360.VisualTest.ts index 194a325c982..e9517738219 100644 --- a/viewer/packages/360-images/visual-tests/Image360.VisualTest.ts +++ b/viewer/packages/360-images/visual-tests/Image360.VisualTest.ts @@ -3,7 +3,12 @@ */ import * as THREE from 'three'; -import { Cdf360EventDescriptorProvider, Cdf360ImageProvider, Local360ImageProvider } from '@reveal/data-providers'; +import { + Cdf360DataModelsDescriptorProvider, + Cdf360EventDescriptorProvider, + Cdf360ImageProvider, + Local360ImageProvider +} from '@reveal/data-providers'; import { StreamingTestFixtureComponents } from '../../../visual-tests/test-fixtures/StreamingVisualTestFixture'; import { StreamingVisualTestFixture } from '../../../visual-tests'; import { Image360Facade } from '../src/Image360Facade'; @@ -16,13 +21,13 @@ import { } from '@reveal/utilities'; import { CogniteClient } from '@cognite/sdk'; import { Image360Entity } from '../src/entity/Image360Entity'; -import { degToRad } from 'three/src/math/MathUtils'; import TWEEN from '@tweenjs/tween.js'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; import { Image360CollectionFactory } from '../src/collection/Image360CollectionFactory'; import { IconOctree } from '@reveal/3d-overlays'; import { OctreeHelper } from 'sparse-octree'; import { Overlay3DIcon } from '@reveal/3d-overlays'; +import { DefaultImage360Collection } from '../src/collection/DefaultImage360Collection'; type CdfImage360Facade = Image360Facade<{ [key: string]: string; @@ -37,18 +42,31 @@ export default class Image360VisualTestFixture extends StreamingVisualTestFixtur camera.near = 0.01; camera.updateProjectionMatrix(); - camera.position.set(11.67, 4.15, -2.89); + camera.position.set(22.67, 4.15, -2.89); camera.rotation.set(-0.4, 0.84, 0.3); const desktopDevice: DeviceDescriptor = { deviceType: 'desktop' }; - const { facade, entities } = await this.setup360Images(cogniteClient, sceneHandler, onBeforeRender, desktopDevice); - entities[1].setIconColor(new THREE.Color(1.0, 0.0, 1.0)); + const { facade, collection } = await this.setup360Images( + cogniteClient, + sceneHandler, + onBeforeRender, + desktopDevice + ); + collection.image360Entities[1].setIconColor(new THREE.Color(1.0, 0.0, 1.0)); + + const collectionTransform = new THREE.Matrix4() + .makeTranslation(10, -5, -7) + .multiply(new THREE.Matrix4().makeRotationX(Math.PI / 4)); + + collection.setModelTransformation(collectionTransform); - const icons = entities.map(entity => entity.icon); - sceneHandler.addObject3D(this.getOctreeVisualizationObject(icons)); + const icons = collection.image360Entities.map(entity => entity.icon); + const octreeVisualizationObject = this.getOctreeVisualizationObject(icons); + octreeVisualizationObject.applyMatrix4(collection.getModelTransformation()); + sceneHandler.addObject3D(octreeVisualizationObject); - this.setupGUI(entities); + this.setupGUI(collection.image360Entities); this.setupMouseMoveEventHandler(renderer, facade, camera); @@ -200,7 +218,7 @@ export default class Image360VisualTestFixture extends StreamingVisualTestFixtur sceneHandler: SceneHandler, onBeforeRender: EventTrigger, device: DeviceDescriptor - ): Promise<{ facade: CdfImage360Facade | LocalImage360Facade; entities: Image360Entity[] }> { + ): Promise<{ facade: CdfImage360Facade | LocalImage360Facade; collection: DefaultImage360Collection }> { if (cogniteClient === undefined) { return this.setupLocal(sceneHandler, onBeforeRender, device); } @@ -208,91 +226,58 @@ export default class Image360VisualTestFixture extends StreamingVisualTestFixtur const queryString = window.location.search; const urlParams = new URLSearchParams(queryString); - if ( - urlParams.get('project') === 'twin-test' && - urlParams.get('modelId') === '946412141563897' && - urlParams.get('revisionId') === '6425532219434724' - ) { - return this.setupTwinTestMauiA(sceneHandler, cogniteClient, onBeforeRender, device); + const siteId = urlParams.get('siteId'); + const externalId = urlParams.get('externalId'); + const space = urlParams.get('space'); + + if (externalId !== null && space !== null) { + return getDM360ImageCollection(cogniteClient, externalId, space); } - if ( - urlParams.get('project') === 'officerobotics' && - urlParams.get('modelId') === '2755498691043825' && - urlParams.get('revisionId') === '141507501940626' - ) { - return this.setupOfficeRobotics(sceneHandler, cogniteClient, onBeforeRender, device); + if (siteId !== null) { + return getEvents360ImageCollection(cogniteClient, siteId); } return this.setupLocal(sceneHandler, onBeforeRender, device); - } - - private async setupOfficeRobotics( - sceneHandler: SceneHandler, - cogniteClient: CogniteClient, - onBeforeRender: EventTrigger, - device: DeviceDescriptor - ): Promise<{ - facade: Image360Facade<{ - [key: string]: string; - }>; - entities: Image360Entity[]; - }> { - const cdf360EventDescriptorProvider = new Cdf360EventDescriptorProvider(cogniteClient); - const cdf360ImageProvider = new Cdf360ImageProvider(cogniteClient, cdf360EventDescriptorProvider); - const image360Factory = new Image360CollectionFactory(cdf360ImageProvider, sceneHandler, onBeforeRender, device); - const image360Facade = new Image360Facade(image360Factory); - const rotation = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), 0.1); - const translation = new THREE.Matrix4().makeTranslation(-18, 1, -13); - const collectionTransform = translation.multiply(rotation); - const collection = await image360Facade.create( - { site_id: '6th floor v3 - enterprise' }, - {}, - collectionTransform, - false - ); - return { facade: image360Facade, entities: collection.image360Entities }; - } - private async setupTwinTestMauiA( - sceneHandler: SceneHandler, - cogniteClient: CogniteClient, - onBeforeRender: EventTrigger, - device: DeviceDescriptor - ): Promise<{ - facade: Image360Facade<{ - [key: string]: string; - }>; - entities: Image360Entity[]; - }> { - const cdf360EventDescriptorProvider = new Cdf360EventDescriptorProvider(cogniteClient); - const cdf360ImageProvider = new Cdf360ImageProvider(cogniteClient, cdf360EventDescriptorProvider); - const image360Factory = new Image360CollectionFactory(cdf360ImageProvider, sceneHandler, onBeforeRender, device); - const image360Facade = new Image360Facade(image360Factory); - - const rotation = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), degToRad(177)); - const translation = new THREE.Matrix4().makeTranslation(11, 49, 32); - const collectionTransform = translation.multiply(rotation); - const collection1 = await image360Facade.create({ site_id: 'helideck-site-2' }, {}, collectionTransform); - - const rotation2 = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), degToRad(40)); - const translation2 = new THREE.Matrix4().makeTranslation(34, 30, 46); - const collectionTransform2 = translation2.multiply(rotation2); - const collection2 = await image360Facade.create({ site_id: 'j-tube-diesel-header-tank' }, {}, collectionTransform2); - - const rotation3 = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), degToRad(96)); - const translation3 = new THREE.Matrix4().makeTranslation(176, 37, 56); - const collectionTransform3 = translation3.multiply(rotation3); - const collection3 = await image360Facade.create( - { site_id: 'se-stairs-module-5-boot-room' }, - {}, - collectionTransform3 - ); + async function getDM360ImageCollection( + cogniteClient: CogniteClient, + externalId: string, + space: string + ): Promise<{ facade: CdfImage360Facade; collection: DefaultImage360Collection }> { + const cdf360EventDescriptorProvider = new Cdf360DataModelsDescriptorProvider(cogniteClient); + const cdf360ImageProvider = new Cdf360ImageProvider(cogniteClient, cdf360EventDescriptorProvider); + const image360Factory = new Image360CollectionFactory( + cdf360ImageProvider, + sceneHandler, + onBeforeRender, + () => {}, + device + ); + const image360Facade = new Image360Facade(image360Factory); + const collection = await image360Facade.create({ image360CollectionExternalId: externalId, space: space }); + + return { facade: image360Facade, collection: collection }; + } - return { - facade: image360Facade, - entities: collection1.image360Entities.concat(collection2.image360Entities, collection3.image360Entities) - }; + async function getEvents360ImageCollection( + cogniteClient: CogniteClient, + siteId: string + ): Promise<{ facade: CdfImage360Facade; collection: DefaultImage360Collection }> { + const cdf360EventDescriptorProvider = new Cdf360EventDescriptorProvider(cogniteClient); + const cdf360ImageProvider = new Cdf360ImageProvider(cogniteClient, cdf360EventDescriptorProvider); + const image360Factory = new Image360CollectionFactory( + cdf360ImageProvider, + sceneHandler, + onBeforeRender, + () => {}, + device + ); + const image360Facade = new Image360Facade(image360Factory); + const collection = await image360Facade.create({ siteId: siteId }); + + return { facade: image360Facade, collection: collection }; + } } private async setupLocal( @@ -301,16 +286,16 @@ export default class Image360VisualTestFixture extends StreamingVisualTestFixtur device: DeviceDescriptor ): Promise<{ facade: Image360Facade; - entities: Image360Entity[]; + collection: DefaultImage360Collection; }> { const queryString = window.location.search; const urlParams = new URLSearchParams(queryString); const modelUrl = urlParams.get('modelUrl') ?? 'primitives'; const dataProvider = new Local360ImageProvider(`${window.location.origin}/${modelUrl}`); - const image360Factory = new Image360CollectionFactory(dataProvider, sceneHandler, onBeforeRender, device); + const image360Factory = new Image360CollectionFactory(dataProvider, sceneHandler, onBeforeRender, () => {}, device); const image360Facade = new Image360Facade(image360Factory); const collection = await image360Facade.create({}); - return { facade: image360Facade, entities: collection.image360Entities }; + return { facade: image360Facade, collection }; } } diff --git a/viewer/packages/360-images/visual-tests/__image_snapshots__/Image360.VisualTest.png b/viewer/packages/360-images/visual-tests/__image_snapshots__/Image360.VisualTest.png index bbd47b31aa9..c74135177f4 100644 Binary files a/viewer/packages/360-images/visual-tests/__image_snapshots__/Image360.VisualTest.png and b/viewer/packages/360-images/visual-tests/__image_snapshots__/Image360.VisualTest.png differ diff --git a/viewer/packages/3d-overlays/src/Overlay3DIcon.ts b/viewer/packages/3d-overlays/src/Overlay3DIcon.ts index 3beb152e77e..368f364dd1a 100644 --- a/viewer/packages/3d-overlays/src/Overlay3DIcon.ts +++ b/viewer/packages/3d-overlays/src/Overlay3DIcon.ts @@ -3,37 +3,45 @@ */ import { assertNever, EventTrigger } from '@reveal/utilities'; -import { PerspectiveCamera, Ray, Sphere, Vector3, Vector4, MathUtils, Color } from 'three'; +import { + PerspectiveCamera, + Ray, + Sphere, + Vector3, + Vector4, + MathUtils, + Color, + Matrix4, + Sprite, + Camera, + Vector2 +} from 'three'; import { Overlay3D } from './Overlay3D'; import { DefaultOverlay3DContentType } from './OverlayCollection'; export type IconParameters = { - position: THREE.Vector3; - color?: THREE.Color; + position: Vector3; + color?: Color; minPixelSize: number; maxPixelSize: number; iconRadius: number; - hoverSprite?: THREE.Sprite; + hoverSprite?: Sprite; }; -export type SetAdaptiveScaleDelegate = (args: { - camera: THREE.Camera; - renderSize: THREE.Vector2; - domElement: HTMLElement; -}) => void; +export type SetAdaptiveScaleDelegate = (args: { camera: Camera; renderSize: Vector2; domElement: HTMLElement }) => void; -export type ParametersChangeDelegate = (event: { color: THREE.Color; visble: boolean }) => void; +export type ParametersChangeDelegate = (event: { color: Color; visble: boolean }) => void; export type SelectedDelegate = (event: { selected: boolean }) => void; export type IconEvent = 'selected' | 'parametersChange'; export class Overlay3DIcon implements Overlay3D { - private readonly _position: THREE.Vector3; + private readonly _position: Vector3; private readonly _minPixelSize: number; private readonly _maxPixelSize: number; private readonly _setAdaptiveScale: SetAdaptiveScaleDelegate; private readonly _iconRadius: number; - private readonly _hoverSprite?: THREE.Sprite; + private readonly _hoverSprite?: Sprite; private readonly _content: ContentType; private readonly _raycastBoundingSphere = new Sphere(); private readonly _defaultColor: Color; @@ -43,6 +51,7 @@ export class Overlay3DIcon implements private _culled = false; private _selected = false; private _color = new Color('white'); + private readonly _worldTransform: Matrix4; private readonly _ndcPosition = new Vector4(); private readonly _events = { @@ -53,6 +62,7 @@ export class Overlay3DIcon implements constructor(iconParameters: IconParameters, content: ContentType) { const { position, minPixelSize, maxPixelSize, iconRadius, hoverSprite, color } = iconParameters; + this._worldTransform = new Matrix4(); this._minPixelSize = minPixelSize; this._maxPixelSize = maxPixelSize; this._iconRadius = iconRadius; @@ -118,7 +128,7 @@ export class Overlay3DIcon implements } updateAdaptiveScale(delegateArguments: { - renderSize: THREE.Vector2; + renderSize: Vector2; camera: PerspectiveCamera; domElement: HTMLElement; }): void { @@ -158,19 +168,23 @@ export class Overlay3DIcon implements return this._culled; } - setVisible(visible: boolean): void { + public setVisible(visible: boolean): void { this._visible = visible; this._events.parametersChange.fire({ color: this._color, visble: visible }); } - getVisible(): boolean { + public getVisible(): boolean { return this._visible && !this._culled; } - getPosition(): Vector3 { + public getPosition(): Vector3 { return this._position; } + public setWorldTransform(matrix: Matrix4): void { + this._worldTransform.copy(matrix); + } + public intersect(ray: Ray): Vector3 | null { this._raycastBoundingSphere.set(this._position, this._adaptiveScale); @@ -182,7 +196,7 @@ export class Overlay3DIcon implements this._events.parametersChange.unsubscribeAll(); } - private setupAdaptiveScaling(position: THREE.Vector3): SetAdaptiveScaleDelegate { + private setupAdaptiveScaling(position: Vector3): SetAdaptiveScaleDelegate { return ({ camera, renderSize, domElement }) => { if (!this.getVisible()) { return; @@ -200,17 +214,20 @@ export class Overlay3DIcon implements } private computeAdaptiveScaling( - position: THREE.Vector3, - renderSize: THREE.Vector2, + position: Vector3, + renderSize: Vector2, domElement: HTMLElement, - camera: THREE.Camera, + camera: Camera, maxHeight: number, minHeight: number, iconRadius: number ) { const { _ndcPosition } = this; _ndcPosition.set(position.x, position.y, position.z, 1); - _ndcPosition.applyMatrix4(camera.matrixWorldInverse).applyMatrix4(camera.projectionMatrix); + _ndcPosition + .applyMatrix4(this._worldTransform) + .applyMatrix4(camera.matrixWorldInverse) + .applyMatrix4(camera.projectionMatrix); if (Math.abs(_ndcPosition.w) < 0.00001) { return 1.0; } diff --git a/viewer/packages/3d-overlays/src/OverlayPointsObject.ts b/viewer/packages/3d-overlays/src/OverlayPointsObject.ts index cd2a610c374..fb0a7e6ad8b 100644 --- a/viewer/packages/3d-overlays/src/OverlayPointsObject.ts +++ b/viewer/packages/3d-overlays/src/OverlayPointsObject.ts @@ -12,6 +12,7 @@ import { GreaterDepth, Group, LessEqualDepth, + Matrix4, Points, RawShaderMaterial, ShaderMaterial, @@ -41,6 +42,8 @@ export class OverlayPointsObject extends Group { private readonly _positionAttribute: BufferAttribute; private readonly _colorBuffer: Float32Array; private readonly _colorAttribute: BufferAttribute; + private readonly _points: { frontPoints: Points; backPoints: Points }; + private _modelTransform: Matrix4; constructor(maxNumberOfPoints: number, materialParameters: OverlayPointsParameters) { super(); @@ -49,6 +52,7 @@ export class OverlayPointsObject extends Group { this._positionAttribute = new BufferAttribute(this._positionBuffer, 3); this._colorBuffer = new Float32Array(maxNumberOfPoints * 3).fill(1); this._colorAttribute = new BufferAttribute(this._colorBuffer, 3); + this._modelTransform = new Matrix4(); geometry.setAttribute('position', this._positionAttribute); geometry.setAttribute('color', this._colorAttribute); geometry.setDrawRange(0, 0); @@ -96,6 +100,7 @@ export class OverlayPointsObject extends Group { this._geometry = geometry; this._frontMaterial = frontMaterial; + this._points = { frontPoints, backPoints }; } public setPoints(points: Vector3[], colors?: Color[]): void { @@ -128,6 +133,26 @@ export class OverlayPointsObject extends Group { this._geometry.computeBoundingSphere(); } + public setTransform(transform: Matrix4): void { + this._points.frontPoints.position.setFromMatrixPosition(transform); + this._points.frontPoints.quaternion.setFromRotationMatrix(transform); + this._points.frontPoints.scale.setFromMatrixScale(transform); + + this._points.backPoints.position.setFromMatrixPosition(transform); + this._points.backPoints.quaternion.setFromRotationMatrix(transform); + this._points.backPoints.scale.setFromMatrixScale(transform); + + this._modelTransform = transform.clone(); + } + + public getTransform(out?: Matrix4): Matrix4 { + if (out !== undefined) { + out.copy(this._modelTransform); + return out; + } + return this._modelTransform.clone(); + } + public dispose(): void { this._frontMaterial.dispose(); this._geometry.dispose(); diff --git a/viewer/packages/api/src/api-helpers/Image360ApiHelper.ts b/viewer/packages/api/src/api-helpers/Image360ApiHelper.ts index 375c7715817..155b75e1b10 100644 --- a/viewer/packages/api/src/api-helpers/Image360ApiHelper.ts +++ b/viewer/packages/api/src/api-helpers/Image360ApiHelper.ts @@ -94,12 +94,16 @@ export class Image360ApiHelper { image360DataModelsDescriptorProvider, image360EventDescriptorProvider ); + + const setNeedsRedraw: () => void = () => (this._needsRedraw = true); + const image360DataProvider = new Cdf360ImageProvider(cogniteClient, combinedDescriptorProvider); const device = determineCurrentDevice(); const image360EntityFactory = new Image360CollectionFactory( image360DataProvider, sceneHandler, onBeforeSceneRendered, + setNeedsRedraw, device, iconsOptions ); diff --git a/viewer/packages/api/src/public/migration/Cognite3DViewer.ts b/viewer/packages/api/src/public/migration/Cognite3DViewer.ts index 5dd3e31ff00..8498bb82254 100644 --- a/viewer/packages/api/src/public/migration/Cognite3DViewer.ts +++ b/viewer/packages/api/src/public/migration/Cognite3DViewer.ts @@ -848,8 +848,7 @@ export class Cognite3DViewer { */ async add360ImageSet( datasource: 'datamodels', - dataModelIdentifier: Image360DataModelIdentifier, - add360ImageOptions?: AddImage360Options + dataModelIdentifier: Image360DataModelIdentifier ): Promise; /** * Adds a set of 360 images to the scene from the /events API in Cognite Data Fusion. diff --git a/viewer/reveal.api.md b/viewer/reveal.api.md index b3b5908530e..2878bb77e8d 100644 --- a/viewer/reveal.api.md +++ b/viewer/reveal.api.md @@ -404,7 +404,7 @@ export class ClusteredAreaCollection implements AreaCollection { // @public (undocumented) export class Cognite3DViewer { constructor(options: Cognite3DViewerOptions); - add360ImageSet(datasource: 'datamodels', dataModelIdentifier: Image360DataModelIdentifier, add360ImageOptions?: AddImage360Options): Promise; + add360ImageSet(datasource: 'datamodels', dataModelIdentifier: Image360DataModelIdentifier): Promise; add360ImageSet(datasource: 'events', eventFilter: { [key: string]: string; }, add360ImageOptions?: AddImage360Options): Promise; @@ -1142,6 +1142,7 @@ export interface Image360Collection { getAssetIds(): Promise; getDefaultAnnotationStyle(): Image360AnnotationAppearance; getIconsVisibility(): boolean; + getModelTransformation(out?: Matrix4): Matrix4; readonly id: string; readonly image360Entities: Image360[]; readonly label: string | undefined; @@ -1154,6 +1155,7 @@ export interface Image360Collection { set360IconCullingRestrictions(radius: number, pointLimit: number): void; setDefaultAnnotationStyle(appearance: Image360AnnotationAppearance): void; setIconsVisibility(visible: boolean): void; + setModelTransformation(matrix: Matrix4): void; targetRevisionDate: Date | undefined; }