simview 4.2.0__tar.gz → 4.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. {simview-4.2.0/simview.egg-info → simview-4.2.1}/PKG-INFO +1 -1
  2. {simview-4.2.0 → simview-4.2.1}/pyproject.toml +1 -1
  3. {simview-4.2.0 → simview-4.2.1}/simview/static/js/SimView.js +18 -5
  4. {simview-4.2.0 → simview-4.2.1}/simview/static/js/components/Scene.js +18 -0
  5. {simview-4.2.0 → simview-4.2.1}/simview/static/js/config.js +9 -0
  6. {simview-4.2.0 → simview-4.2.1}/simview/static/js/objects/Body.js +43 -3
  7. {simview-4.2.0 → simview-4.2.1}/simview/static/js/ui/BodyStateWindow.js +6 -1
  8. {simview-4.2.0 → simview-4.2.1}/simview/static/js/ui/Controls.js +46 -7
  9. {simview-4.2.0 → simview-4.2.1}/simview/static/js/ui/ScalarPlotter.js +35 -3
  10. simview-4.2.1/simview/static/js/utils/cameraRange.js +37 -0
  11. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/viewState.js +6 -0
  12. {simview-4.2.0 → simview-4.2.1/simview.egg-info}/PKG-INFO +1 -1
  13. {simview-4.2.0 → simview-4.2.1}/simview.egg-info/SOURCES.txt +1 -0
  14. {simview-4.2.0 → simview-4.2.1}/LICENSE +0 -0
  15. {simview-4.2.0 → simview-4.2.1}/MANIFEST.in +0 -0
  16. {simview-4.2.0 → simview-4.2.1}/README.md +0 -0
  17. {simview-4.2.0 → simview-4.2.1}/setup.cfg +0 -0
  18. {simview-4.2.0 → simview-4.2.1}/simview/__init__.py +0 -0
  19. {simview-4.2.0 → simview-4.2.1}/simview/__main__.py +0 -0
  20. {simview-4.2.0 → simview-4.2.1}/simview/columnar.py +0 -0
  21. {simview-4.2.0 → simview-4.2.1}/simview/diff.py +0 -0
  22. {simview-4.2.0 → simview-4.2.1}/simview/info.py +0 -0
  23. {simview-4.2.0 → simview-4.2.1}/simview/launcher.py +0 -0
  24. {simview-4.2.0 → simview-4.2.1}/simview/live.py +0 -0
  25. {simview-4.2.0 → simview-4.2.1}/simview/merge.py +0 -0
  26. {simview-4.2.0 → simview-4.2.1}/simview/model.py +0 -0
  27. {simview-4.2.0 → simview-4.2.1}/simview/py.typed +0 -0
  28. {simview-4.2.0 → simview-4.2.1}/simview/remote.py +0 -0
  29. {simview-4.2.0 → simview-4.2.1}/simview/render.py +0 -0
  30. {simview-4.2.0 → simview-4.2.1}/simview/scene.py +0 -0
  31. {simview-4.2.0 → simview-4.2.1}/simview/server.py +0 -0
  32. {simview-4.2.0 → simview-4.2.1}/simview/state.py +0 -0
  33. {simview-4.2.0 → simview-4.2.1}/simview/static/css/controls.css +0 -0
  34. {simview-4.2.0 → simview-4.2.1}/simview/static/js/components/AnimationController.js +0 -0
  35. {simview-4.2.0 → simview-4.2.1}/simview/static/js/components/BatchManager.js +0 -0
  36. {simview-4.2.0 → simview-4.2.1}/simview/static/js/components/InteractionController.js +0 -0
  37. {simview-4.2.0 → simview-4.2.1}/simview/static/js/components/InteractionControls.js +0 -0
  38. {simview-4.2.0 → simview-4.2.1}/simview/static/js/components/StateStore.js +0 -0
  39. {simview-4.2.0 → simview-4.2.1}/simview/static/js/components/WindowedField.js +0 -0
  40. {simview-4.2.0 → simview-4.2.1}/simview/static/js/main.js +0 -0
  41. {simview-4.2.0 → simview-4.2.1}/simview/static/js/objects/StaticObject.js +0 -0
  42. {simview-4.2.0 → simview-4.2.1}/simview/static/js/objects/Terrain.js +0 -0
  43. {simview-4.2.0 → simview-4.2.1}/simview/static/js/objects/colormap.js +0 -0
  44. {simview-4.2.0 → simview-4.2.1}/simview/static/js/objects/similarity.js +0 -0
  45. {simview-4.2.0 → simview-4.2.1}/simview/static/js/objects/utils.js +0 -0
  46. {simview-4.2.0 → simview-4.2.1}/simview/static/js/ui/AnalysisPanel.js +0 -0
  47. {simview-4.2.0 → simview-4.2.1}/simview/static/js/ui/BatchLegend.js +0 -0
  48. {simview-4.2.0 → simview-4.2.1}/simview/static/js/ui/ErrorMetrics.js +0 -0
  49. {simview-4.2.0 → simview-4.2.1}/simview/static/js/ui/Legend.js +0 -0
  50. {simview-4.2.0 → simview-4.2.1}/simview/static/js/ui/PlaybackControls.js +0 -0
  51. {simview-4.2.0 → simview-4.2.1}/simview/static/js/ui/TerrainProfile.js +0 -0
  52. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/batchPresets.js +0 -0
  53. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/batchVisibility.js +0 -0
  54. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/blobCodec.js +0 -0
  55. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/blobWindow.js +0 -0
  56. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/bodyTransforms.js +0 -0
  57. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/csv.js +0 -0
  58. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/episodes.js +0 -0
  59. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/errorMath.js +0 -0
  60. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/injectStyles.js +0 -0
  61. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/interpolate.js +0 -0
  62. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/liveFollow.js +0 -0
  63. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/loadRecordingLibs.js +0 -0
  64. {simview-4.2.0 → simview-4.2.1}/simview/static/js/utils/terrainSample.js +0 -0
  65. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/index.min.js +0 -0
  66. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/Color.js +0 -0
  67. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/chroma.js +0 -0
  68. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/colors/colorbrewer.js +0 -0
  69. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/colors/w3cx11.js +0 -0
  70. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/generator/average.js +0 -0
  71. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/generator/bezier.js +0 -0
  72. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/generator/blend.js +0 -0
  73. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/generator/cubehelix.js +0 -0
  74. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/generator/mix.js +0 -0
  75. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/generator/random.js +0 -0
  76. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/generator/scale.js +0 -0
  77. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/interpolator/_hsx.js +0 -0
  78. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/interpolator/hcg.js +0 -0
  79. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/interpolator/hsi.js +0 -0
  80. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/interpolator/hsl.js +0 -0
  81. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/interpolator/hsv.js +0 -0
  82. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/interpolator/index.js +0 -0
  83. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/interpolator/lab.js +0 -0
  84. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/interpolator/lch.js +0 -0
  85. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/interpolator/lrgb.js +0 -0
  86. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/interpolator/num.js +0 -0
  87. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/interpolator/oklab.js +0 -0
  88. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/interpolator/oklch.js +0 -0
  89. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/interpolator/rgb.js +0 -0
  90. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/cmyk/cmyk2rgb.js +0 -0
  91. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/cmyk/index.js +0 -0
  92. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/cmyk/rgb2cmyk.js +0 -0
  93. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/css/css2rgb.js +0 -0
  94. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/css/hsl2css.js +0 -0
  95. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/css/index.js +0 -0
  96. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/css/lab2css.js +0 -0
  97. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/css/lch2css.js +0 -0
  98. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/css/oklab2css.js +0 -0
  99. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/css/oklch2css.js +0 -0
  100. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/css/rgb2css.js +0 -0
  101. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/gl/index.js +0 -0
  102. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hcg/hcg2rgb.js +0 -0
  103. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hcg/index.js +0 -0
  104. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hcg/rgb2hcg.js +0 -0
  105. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hex/hex2rgb.js +0 -0
  106. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hex/index.js +0 -0
  107. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hex/rgb2hex.js +0 -0
  108. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hsi/hsi2rgb.js +0 -0
  109. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hsi/index.js +0 -0
  110. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hsi/rgb2hsi.js +0 -0
  111. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hsl/hsl2rgb.js +0 -0
  112. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hsl/index.js +0 -0
  113. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hsl/rgb2hsl.js +0 -0
  114. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hsv/hsv2rgb.js +0 -0
  115. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hsv/index.js +0 -0
  116. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/hsv/rgb2hsv.js +0 -0
  117. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/input.js +0 -0
  118. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/lab/index.js +0 -0
  119. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/lab/lab-constants.js +0 -0
  120. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/lab/lab2rgb.js +0 -0
  121. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/lab/rgb2lab.js +0 -0
  122. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/lch/hcl2rgb.js +0 -0
  123. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/lch/index.js +0 -0
  124. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/lch/lab2lch.js +0 -0
  125. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/lch/lch2lab.js +0 -0
  126. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/lch/lch2rgb.js +0 -0
  127. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/lch/rgb2lch.js +0 -0
  128. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/named/index.js +0 -0
  129. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/num/index.js +0 -0
  130. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/num/num2rgb.js +0 -0
  131. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/num/rgb2num.js +0 -0
  132. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/oklab/index.js +0 -0
  133. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/oklab/oklab2rgb.js +0 -0
  134. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/oklab/rgb2oklab.js +0 -0
  135. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/oklch/index.js +0 -0
  136. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/oklch/oklch2rgb.js +0 -0
  137. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/oklch/rgb2oklch.js +0 -0
  138. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/rgb/index.js +0 -0
  139. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/temp/index.js +0 -0
  140. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/temp/rgb2temperature.js +0 -0
  141. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/io/temp/temperature2rgb.js +0 -0
  142. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/ops/alpha.js +0 -0
  143. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/ops/clipped.js +0 -0
  144. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/ops/darken.js +0 -0
  145. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/ops/get.js +0 -0
  146. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/ops/luminance.js +0 -0
  147. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/ops/mix.js +0 -0
  148. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/ops/premultiply.js +0 -0
  149. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/ops/saturate.js +0 -0
  150. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/ops/set.js +0 -0
  151. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/ops/shade.js +0 -0
  152. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/analyze.js +0 -0
  153. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/clip_rgb.js +0 -0
  154. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/contrast.js +0 -0
  155. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/contrastAPCA.js +0 -0
  156. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/delta-e.js +0 -0
  157. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/distance.js +0 -0
  158. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/index.js +0 -0
  159. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/last.js +0 -0
  160. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/limit.js +0 -0
  161. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/multiply-matrices.js +0 -0
  162. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/scales.js +0 -0
  163. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/type.js +0 -0
  164. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/unpack.js +0 -0
  165. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/utils/valid.js +0 -0
  166. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/chroma-js-3.1.2/src/version.js +0 -0
  167. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/download.js +0 -0
  168. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/js-colormaps.js +0 -0
  169. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/tar.js +0 -0
  170. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/three-0.174.0/addons/controls/OrbitControls.js +0 -0
  171. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/three-0.174.0/addons/libs/lil-gui.module.min.js +0 -0
  172. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/three-0.174.0/three.core.js +0 -0
  173. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/three-0.174.0/three.module.js +0 -0
  174. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/uPlot.esm.js +0 -0
  175. {simview-4.2.0 → simview-4.2.1}/simview/static/lib/uPlot.min.css +0 -0
  176. {simview-4.2.0 → simview-4.2.1}/simview/static/textures/contacts/red-cross0.png +0 -0
  177. {simview-4.2.0 → simview-4.2.1}/simview/static/textures/points/ball0.png +0 -0
  178. {simview-4.2.0 → simview-4.2.1}/simview/static/textures/points/ball1.png +0 -0
  179. {simview-4.2.0 → simview-4.2.1}/simview/templates/index.html +0 -0
  180. {simview-4.2.0 → simview-4.2.1}/simview/terrain.py +0 -0
  181. {simview-4.2.0 → simview-4.2.1}/simview/utils.py +0 -0
  182. {simview-4.2.0 → simview-4.2.1}/simview.egg-info/dependency_links.txt +0 -0
  183. {simview-4.2.0 → simview-4.2.1}/simview.egg-info/entry_points.txt +0 -0
  184. {simview-4.2.0 → simview-4.2.1}/simview.egg-info/requires.txt +0 -0
  185. {simview-4.2.0 → simview-4.2.1}/simview.egg-info/top_level.txt +0 -0
  186. {simview-4.2.0 → simview-4.2.1}/tests/test_batch_selection.py +0 -0
  187. {simview-4.2.0 → simview-4.2.1}/tests/test_cli.py +0 -0
  188. {simview-4.2.0 → simview-4.2.1}/tests/test_columnar_ondisk.py +0 -0
  189. {simview-4.2.0 → simview-4.2.1}/tests/test_columnar_states.py +0 -0
  190. {simview-4.2.0 → simview-4.2.1}/tests/test_contacts.py +0 -0
  191. {simview-4.2.0 → simview-4.2.1}/tests/test_diff.py +0 -0
  192. {simview-4.2.0 → simview-4.2.1}/tests/test_episodes.py +0 -0
  193. {simview-4.2.0 → simview-4.2.1}/tests/test_info.py +0 -0
  194. {simview-4.2.0 → simview-4.2.1}/tests/test_launcher.py +0 -0
  195. {simview-4.2.0 → simview-4.2.1}/tests/test_live.py +0 -0
  196. {simview-4.2.0 → simview-4.2.1}/tests/test_merge.py +0 -0
  197. {simview-4.2.0 → simview-4.2.1}/tests/test_pointcloud_features.py +0 -0
  198. {simview-4.2.0 → simview-4.2.1}/tests/test_remote.py +0 -0
  199. {simview-4.2.0 → simview-4.2.1}/tests/test_roundtrip.py +0 -0
  200. {simview-4.2.0 → simview-4.2.1}/tests/test_scene.py +0 -0
  201. {simview-4.2.0 → simview-4.2.1}/tests/test_server.py +0 -0
  202. {simview-4.2.0 → simview-4.2.1}/tests/test_show.py +0 -0
  203. {simview-4.2.0 → simview-4.2.1}/tests/test_terrain.py +0 -0
  204. {simview-4.2.0 → simview-4.2.1}/tests/test_terrain_query.py +0 -0
  205. {simview-4.2.0 → simview-4.2.1}/tests/test_trajectory.py +0 -0
  206. {simview-4.2.0 → simview-4.2.1}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simview
3
- Version: 4.2.0
3
+ Version: 4.2.1
4
4
  Summary: THREE.js-based simulation visualization tool
5
5
  Author-email: Jan Vlk <vlkjan6@fel.cvut.cz>, Ales Kucera <kuceral4@fel.cvut.cz>, David Korcak <david.korcak@gmail.com>
6
6
  License-Expression: BSD-3-Clause
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "simview"
7
- version = "4.2.0"
7
+ version = "4.2.1"
8
8
  readme = "README.md"
9
9
  requires-python = ">=3.12"
10
10
  license = "BSD-3-Clause"
@@ -383,6 +383,10 @@ export class SimView {
383
383
  }
384
384
  }
385
385
  this.appendBodyHistories(0);
386
+ // Whether a point-cloud body is listed depends on whether it turned
387
+ // out to carry per-frame data, which is only knowable now that
388
+ // appendBodyHistories has run (see BodyStateWindow.updateBodyList).
389
+ if (this.bodyStateWindow) this.bodyStateWindow.updateBodyList();
386
390
  if (this.errorMetrics) {
387
391
  this.errorMetrics.onHistoryReady();
388
392
  }
@@ -464,12 +468,18 @@ export class SimView {
464
468
  this.batchManager = new BatchManager(this, model);
465
469
  this.bodies = new Map();
466
470
 
467
- // Auto-detect visualization mode based on first body: anything with a
468
- // real surface (box/sphere/cylinder/mesh) defaults to mesh; pointclouds
469
- // keep the default points mode.
471
+ // Auto-detect visualization mode from the first body the mode
472
+ // actually governs: anything with a real surface
473
+ // (box/sphere/cylinder/mesh) defaults to mesh. Point clouds are
474
+ // skipped rather than inspected -- they're outside the mode
475
+ // entirely (see Body#pointsVisible), and model.bodies[0] being a
476
+ // cloud must not leave a scene full of meshes defaulting to a
477
+ // mode that renders none of them.
470
478
  if (Array.isArray(model.bodies) && model.bodies.length > 0) {
471
- const firstShape = model.bodies[0].shape;
472
- if (firstShape && firstShape.type !== "pointcloud") {
479
+ const firstSolid = model.bodies.find(
480
+ (b) => b.shape && b.shape.type !== "pointcloud"
481
+ );
482
+ if (firstSolid) {
473
483
  console.log("Auto-switching visualization mode to 'mesh' based on body type");
474
484
  this.uiState.bodyVisualizationMode = "mesh";
475
485
  }
@@ -498,6 +508,9 @@ export class SimView {
498
508
  console.debug("Using terrain data");
499
509
  this.terrain = new Terrain(model.terrain, this);
500
510
  this.scene.addObject3D(this.terrain.getObject3D());
511
+ // Terrain extent is what tells us how far this scene reaches,
512
+ // so the camera's clipping/orbit range can stop being a guess.
513
+ this.scene.applySceneExtent(this.terrain.bounds);
501
514
  } else {
502
515
  throw new Error("Terrain data is missing in model");
503
516
  }
@@ -4,8 +4,10 @@ import {
4
4
  SCENE_CONFIG,
5
5
  RENDERER_CONFIG,
6
6
  CAMERA_CONFIG,
7
+ CONTROLS_CONFIG,
7
8
  LIGHTING_CONFIG,
8
9
  } from "../config.js";
10
+ import { cameraRangeForBounds } from "../utils/cameraRange.js";
9
11
 
10
12
  export class Scene {
11
13
  constructor(app) {
@@ -31,6 +33,22 @@ export class Scene {
31
33
  this.setupWindowHandlers();
32
34
  }
33
35
 
36
+ // Sizes the camera's far plane and the orbit distance limit to the scene
37
+ // actually being viewed. Called once the terrain is known (see
38
+ // SimView.initFromModel) -- the config defaults are floors chosen for
39
+ // small scenes, and a several-hundred-metre recording clips against them.
40
+ applySceneExtent(bounds) {
41
+ const { far, maxDistance } = cameraRangeForBounds(bounds, {
42
+ far: CAMERA_CONFIG.far,
43
+ maxDistance: CONTROLS_CONFIG.maxDistance,
44
+ });
45
+ if (this.camera && this.camera.far !== far) {
46
+ this.camera.far = far;
47
+ this.camera.updateProjectionMatrix();
48
+ }
49
+ if (this.controls) this.controls.maxDistance = maxDistance;
50
+ }
51
+
34
52
  setupWindowHandlers() {
35
53
  window.addEventListener("resize", () => this.#handleWindowResize());
36
54
  window.addEventListener("error", (event) => this.#handleError(event));
@@ -1,5 +1,9 @@
1
1
  export const UI_DEFAULT_CONFIG = {
2
2
  bodyVisualizationMode: "points",
3
+ // Point-cloud bodies sit outside Body Visualization Mode (a cloud isn't a
4
+ // way of drawing a body, it's the whole object), so they get their own
5
+ // visibility toggle -- see Body#pointsVisible.
6
+ pointCloudsVisible: true,
3
7
  axesVisible: false,
4
8
  trailsVisible: false,
5
9
  smoothInterpolation: true,
@@ -31,6 +35,8 @@ export const FREQ_CONFIG = {
31
35
 
32
36
  export const CONTROLS_CONFIG = {
33
37
  minDistance: 1,
38
+ // Also a floor, widened alongside the far plane so the whole scene can
39
+ // actually be framed on a large map (see Scene.applySceneExtent).
34
40
  maxDistance: 500,
35
41
  enableDamping: false,
36
42
  dampingFactor: 0.05,
@@ -58,6 +64,9 @@ export const RENDERER_CONFIG = {
58
64
  export const CAMERA_CONFIG = {
59
65
  fov: 40,
60
66
  near: 0.1,
67
+ // A floor, not the final value: widened at load to span the terrain
68
+ // extent, so scenes hundreds of metres across don't clip their own
69
+ // terrain and bodies away (see Scene.applySceneExtent).
61
70
  far: 500,
62
71
  position: [-15, -15, 10],
63
72
  up: [0, 0, 1],
@@ -86,6 +86,10 @@ export class Body {
86
86
  this.bodyVectors = [];
87
87
  this.contactPoints = [];
88
88
  this.contactPointSizes = [];
89
+ // A point cloud is its own kind of object rather than a body drawn
90
+ // "as points", so it stays out of Body Visualization Mode entirely --
91
+ // "none" included -- and follows setPointCloudsVisible instead.
92
+ this.isPointCloud = bodyData.shape?.type === "pointcloud";
89
93
  this.representations = { mesh: [], wireframe: [], points: [] };
90
94
  this.createBatchGroups(bodyData);
91
95
 
@@ -356,8 +360,7 @@ export class Body {
356
360
  if (this.batchGroups[i]) this.batchGroups[i].visible = visible;
357
361
  const pointsRep = this.representations["points"];
358
362
  if (Array.isArray(pointsRep) && pointsRep[i]) {
359
- pointsRep[i].visible =
360
- visible && this.app.uiState.bodyVisualizationMode === "points";
363
+ pointsRep[i].visible = visible && this.#pointsVisible();
361
364
  }
362
365
  if (this.contactPoints[i]) {
363
366
  this.contactPoints[i].visible =
@@ -370,6 +373,26 @@ export class Body {
370
373
  this.updateAllInstances();
371
374
  }
372
375
 
376
+ // Should this body's points be on screen right now? A point-cloud body
377
+ // answers to its own "Show Point Clouds" toggle; every other body's
378
+ // points are one of its visualization modes, like mesh and wireframe.
379
+ #pointsVisible() {
380
+ return this.isPointCloud
381
+ ? this.app.uiState.pointCloudsVisible !== false
382
+ : this.app.uiState.bodyVisualizationMode === "points";
383
+ }
384
+
385
+ // Applies the "Show Point Clouds" toggle. A no-op on bodies that aren't
386
+ // point clouds -- their points belong to the visualization mode instead.
387
+ setPointCloudsVisible(visible) {
388
+ if (!this.isPointCloud) return;
389
+ const pointsRep = this.representations["points"];
390
+ if (!Array.isArray(pointsRep)) return;
391
+ pointsRep.forEach((points, i) => {
392
+ if (points) points.visible = visible && this.#isBatchVisible(i);
393
+ });
394
+ }
395
+
373
396
  #isBatchVisible(batchIndex) {
374
397
  const batchManager = this.app.batchManager;
375
398
  return batchManager?.isBatchVisible
@@ -415,7 +438,7 @@ export class Body {
415
438
  this.pointColors
416
439
  );
417
440
  if (!points) return;
418
- points.visible = this.app.uiState.bodyVisualizationMode === "points";
441
+ points.visible = this.#pointsVisible();
419
442
  // Lets InteractionController resolve a raycast hit back to this
420
443
  // body/batch without a reverse lookup.
421
444
  points.userData.bodyName = this.name;
@@ -463,6 +486,15 @@ export class Body {
463
486
 
464
487
  const instancedMesh = new THREE.InstancedMesh(source, material, this.simBatches);
465
488
  instancedMesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
489
+ // Instances are placed by setMatrixAt (see updateInstanceMatrix),
490
+ // which leaves this object's own matrixWorld at identity. THREE
491
+ // computes an InstancedMesh's bounding sphere lazily on the first
492
+ // frustum test and then caches it forever -- instanceMatrix.needsUpdate
493
+ // does not invalidate it -- so bodies that travel away from wherever
494
+ // they started get culled wholesale once that stale sphere leaves the
495
+ // frustum. Skip the test rather than recomputing the sphere every
496
+ // frame across every batch; trails do the same for the same reason.
497
+ instancedMesh.frustumCulled = false;
466
498
  instancedMesh.visible = this.app.uiState.bodyVisualizationMode === type;
467
499
  instancedMesh.castShadow = (type === "mesh");
468
500
  instancedMesh.receiveShadow = (type === "mesh");
@@ -696,6 +728,9 @@ export class Body {
696
728
 
697
729
  updateVisualizationMode(mode) {
698
730
  for (const [type, obj] of Object.entries(this.representations)) {
731
+ // A point cloud isn't one of the modes, so nothing the mode
732
+ // switch does -- including "none" -- should touch it.
733
+ if (type === "points" && this.isPointCloud) continue;
699
734
  if (obj instanceof THREE.InstancedMesh) {
700
735
  obj.visible = type === mode;
701
736
  } else if (Array.isArray(obj)) {
@@ -804,7 +839,12 @@ export class Body {
804
839
 
805
840
  // Which of the mesh/wireframe/points representations this body actually has,
806
841
  // so the UI can only offer visualization modes that will show something.
842
+ // A point-cloud body reports none: its cloud is the object itself, not a
843
+ // way of drawing it, and it has its own toggle (see #pointsVisible). That
844
+ // keeps "points" out of the dropdown unless some body really does carry
845
+ // body-points, which is what made selecting it blank out every mesh body.
807
846
  getAvailableVisualizationModes() {
847
+ if (this.isPointCloud) return [];
808
848
  const modes = [];
809
849
  for (const type of ["mesh", "wireframe", "points"]) {
810
850
  const rep = this.representations[type];
@@ -310,7 +310,12 @@ export class BodyStateWindow {
310
310
  const list = document.createElement("ul");
311
311
  list.classList.add("body-list"); // Use CSS class
312
312
 
313
- for (const name of this.app.bodies.keys()) {
313
+ for (const [name, body] of this.app.bodies) {
314
+ // A point cloud with no per-frame data is a static prop, not a
315
+ // body with a pose worth reading -- listing it only offers a
316
+ // permanently-zero Position/Rotation row. One that does move
317
+ // (validStates > 0) stays listed like any other body.
318
+ if (body.isPointCloud && !(body.validStates > 0)) continue;
314
319
  const item = document.createElement("li");
315
320
  item.classList.add("body-list-item"); // Use CSS class
316
321
  item.textContent = name;
@@ -8,6 +8,7 @@ export class UIControls {
8
8
  this.app = app;
9
9
  this.attributeAvailability = this.determineAttributeAvailability();
10
10
  this.visualizationModes = this.determineAvailableVisualizationModes();
11
+ this.hasPointClouds = this.determineHasPointClouds();
11
12
  this.gui = this.createDatGUI();
12
13
  this.keyboardControlsListener = null;
13
14
  this.setupKeyboardControls(app);
@@ -44,15 +45,27 @@ export class UIControls {
44
45
 
45
46
  // Union of visualization modes actually available across all bodies, plus a
46
47
  // "none" option to hide bodies entirely (e.g. for terrain-only viewing).
48
+ // Point-cloud bodies contribute nothing and are unaffected by the mode --
49
+ // they have their own toggle -- so a scene of nothing but point clouds
50
+ // gets no mode control at all rather than a dropdown that only hides things.
47
51
  determineAvailableVisualizationModes() {
48
52
  const modes = new Set();
49
53
  this.app.bodies.forEach((body) => {
50
54
  body.getAvailableVisualizationModes().forEach((m) => modes.add(m));
51
55
  });
56
+ if (modes.size === 0) return [];
52
57
  modes.add("none");
53
58
  return [...modes];
54
59
  }
55
60
 
61
+ determineHasPointClouds() {
62
+ let found = false;
63
+ this.app.bodies.forEach((body) => {
64
+ if (body.isPointCloud) found = true;
65
+ });
66
+ return found;
67
+ }
68
+
56
69
  changeTargetBatch(key) {
57
70
  const { scene, batchManager } = this.app;
58
71
  const currentBatchTarget = batchManager.currentlyActiveBatch;
@@ -98,7 +111,10 @@ export class UIControls {
98
111
  // Only show body-related controls when there's actually a body to control
99
112
  if (this.app.bodies && this.app.bodies.size > 0) {
100
113
  let defaultVisualizationMode = this.app.uiState.bodyVisualizationMode;
101
- if (!this.visualizationModes.includes(defaultVisualizationMode)) {
114
+ if (
115
+ this.visualizationModes.length > 0 &&
116
+ !this.visualizationModes.includes(defaultVisualizationMode)
117
+ ) {
102
118
  defaultVisualizationMode =
103
119
  this.visualizationModes.find((m) => m !== "none") || "none";
104
120
  this.app.uiState.bodyVisualizationMode = defaultVisualizationMode;
@@ -106,6 +122,7 @@ export class UIControls {
106
122
 
107
123
  const controls = {
108
124
  bodyVisualizationMode: defaultVisualizationMode,
125
+ showPointClouds: this.app.uiState.pointCloudsVisible !== false,
109
126
  showAxes: this.app.uiState.axesVisible,
110
127
  showTrails: this.app.uiState.trailsVisible,
111
128
  smoothInterpolation: this.app.uiState.smoothInterpolation,
@@ -118,12 +135,24 @@ export class UIControls {
118
135
 
119
136
  this.bodyFolder = this.gui.addFolder("Body Options");
120
137
 
121
- this.bodyFolder
122
- .add(controls, "bodyVisualizationMode", this.visualizationModes)
123
- .name("Body Visualization Mode (B)")
124
- .onChange((value) => {
125
- this.updateVisualizationMode(value);
126
- });
138
+ // Nothing to switch between when every body is a point cloud.
139
+ if (this.visualizationModes.length > 0) {
140
+ this.bodyFolder
141
+ .add(controls, "bodyVisualizationMode", this.visualizationModes)
142
+ .name("Body Visualization Mode (B)")
143
+ .onChange((value) => {
144
+ this.updateVisualizationMode(value);
145
+ });
146
+ }
147
+
148
+ if (this.hasPointClouds) {
149
+ this.bodyFolder
150
+ .add(controls, "showPointClouds")
151
+ .name("Show Point Clouds")
152
+ .onChange((value) => {
153
+ this.updatePointCloudsVisibility(value);
154
+ });
155
+ }
127
156
 
128
157
  this.bodyFolder
129
158
  .add(controls, "showAxes")
@@ -629,6 +658,7 @@ export class UIControls {
629
658
  switch (event.key.toLowerCase()) {
630
659
  case "b":
631
660
  const modes = this.visualizationModes;
661
+ if (modes.length === 0) break;
632
662
  const currentIndex = modes.indexOf(
633
663
  this.app.uiState.bodyVisualizationMode
634
664
  );
@@ -710,6 +740,15 @@ export class UIControls {
710
740
  this.app.uiState.bodyVisualizationMode = mode;
711
741
  }
712
742
 
743
+ // Point-cloud bodies are outside Body Visualization Mode (see
744
+ // Body#pointsVisible), so their visibility rides on this instead.
745
+ updatePointCloudsVisibility(visible) {
746
+ this.app.uiState.pointCloudsVisible = visible;
747
+ this.app.bodies.forEach((body) => {
748
+ if (body.setPointCloudsVisible) body.setPointCloudsVisible(visible);
749
+ });
750
+ }
751
+
713
752
  updateAxesVisibility(show) {
714
753
  this.app.bodies.forEach((body) => {
715
754
  body.toggleAxes(show);
@@ -391,6 +391,16 @@ export class ScalarPlotter {
391
391
  );
392
392
  }
393
393
 
394
+ // uPlot walks `incrs` and takes the first increment whose ticks fit the
395
+ // axis's available length. Offering exactly one (range/stepsPerYAxis) meant
396
+ // that in a short panel -- which is what the Analysis panel gives us -- no
397
+ // increment fit, and uPlot drew no ticks or labels at all. Coarser
398
+ // multiples let it degrade instead of giving up.
399
+ _yIncrements(min, max) {
400
+ const base = this.getChartInterval(min, max);
401
+ return [1, 2, 5, 10, 20, 50, 100].map((m) => base * m);
402
+ }
403
+
394
404
  getChartInterval(min, max) {
395
405
  const diff = max - min;
396
406
  if (diff === 0)
@@ -419,6 +429,17 @@ export class ScalarPlotter {
419
429
  return bestBatch;
420
430
  }
421
431
 
432
+ // The x extent every chart's scale is pinned to: the whole timeline. Falls
433
+ // back to a unit span when there are no times, so uPlot is never handed
434
+ // NaN/undefined bounds.
435
+ _timeExtent() {
436
+ const n = this.times?.length ?? 0;
437
+ if (n === 0) return [0, 1];
438
+ const first = this.times[0];
439
+ const last = this.times[n - 1];
440
+ return last > first ? [first, last] : [first, first + 1];
441
+ }
442
+
422
443
  _initializePlots() {
423
444
  const limOffset = 1e-2;
424
445
  this.scalarNames.forEach((name) => {
@@ -445,7 +466,15 @@ export class ScalarPlotter {
445
466
  padding: [8, 8, 0, 8],
446
467
  series,
447
468
  scales: {
448
- x: { time: false, min: this.times[0], max: this.times[this.times.length - 1] },
469
+ // uPlot treats a scale's `min`/`max` as outputs, not as
470
+ // a pin: the initial autoscale over the empty data
471
+ // passed below nulls them, and every later update goes
472
+ // through setData(data, false), which never revisits x.
473
+ // That left x null forever -- valToPos NaN, nothing
474
+ // drawn. `range` is the actual pin (the same thing
475
+ // ErrorMetrics does), and this axis is meant to span the
476
+ // whole timeline regardless, with the line growing into it.
477
+ x: { time: false, range: () => this._timeExtent() },
449
478
  y: { min, max },
450
479
  },
451
480
  axes: [
@@ -463,7 +492,7 @@ export class ScalarPlotter {
463
492
  ticks: { stroke: "rgb(73, 73, 73)" },
464
493
  font: "12px Arial",
465
494
  space: 30,
466
- incrs: [this.getChartInterval(min, max)],
495
+ incrs: this._yIncrements(min, max),
467
496
  },
468
497
  ],
469
498
  legend: { show: false },
@@ -667,7 +696,10 @@ export class ScalarPlotter {
667
696
  }
668
697
 
669
698
  if (!needRender) return;
670
- activeChart.redraw(false, true);
699
+ // rebuildPaths must be true: the series data changes on every frame of
700
+ // playback, and redrawing without rebuilding just repaints the paths
701
+ // built for whatever data the chart first saw.
702
+ activeChart.redraw(true, true);
671
703
  }
672
704
 
673
705
  animate(now) {
@@ -0,0 +1,37 @@
1
+ // How far the camera has to see, and how far out it may orbit, for a scene of
2
+ // a given horizontal extent. Pure arithmetic, no THREE/DOM, so it's unit
3
+ // testable on its own (see tests/js/cameraRange.test.js).
4
+ //
5
+ // The defaults in config.js are sized for the small scenes SimView started
6
+ // with (a few tens of metres). On a real recording -- a robot driving a few
7
+ // hundred metres across a mapped terrain -- a fixed 500 m far plane clips the
8
+ // terrain, and a fixed 500 m orbit limit means the whole run can never be
9
+ // framed at once. Both are treated as floors and widened from the terrain
10
+ // bounds instead.
11
+
12
+ // Framing a scene of diameter D at SimView's ~40 degree vertical FOV needs the
13
+ // camera roughly D / (2 * tan(fov/2)) ~= 1.4 * D away from the centre, so the
14
+ // orbit limit is 1.5 * D and the far plane covers that viewpoint plus the far
15
+ // side of the scene (2.5 * D), with a little margin on top.
16
+ const ORBIT_FACTOR = 1.5;
17
+ const FAR_FACTOR = 3;
18
+
19
+ export function cameraRangeForBounds(bounds, defaults = {}) {
20
+ const far = Number.isFinite(defaults.far) ? defaults.far : 0;
21
+ const maxDistance = Number.isFinite(defaults.maxDistance)
22
+ ? defaults.maxDistance
23
+ : 0;
24
+ const fallback = { far, maxDistance };
25
+
26
+ if (!bounds || typeof bounds !== "object") return fallback;
27
+ const { minX, maxX, minY, maxY } = bounds;
28
+ if (![minX, maxX, minY, maxY].every((v) => Number.isFinite(v))) return fallback;
29
+
30
+ const diagonal = Math.hypot(maxX - minX, maxY - minY);
31
+ if (!(diagonal > 0)) return fallback;
32
+
33
+ return {
34
+ far: Math.max(far, diagonal * FAR_FACTOR),
35
+ maxDistance: Math.max(maxDistance, diagonal * ORBIT_FACTOR),
36
+ };
37
+ }
@@ -30,6 +30,12 @@ const BOOLEAN_FLAG_KEYS = [
30
30
  "terrainVisualizationModes.normals",
31
31
  ];
32
32
 
33
+ // Deliberately NOT in the list above: `pointCloudsVisible`. Appending only
34
+ // works for flags that default off -- a link made before the flag existed has
35
+ // no bit for it, which decodes as false, so a default-on flag would arrive
36
+ // switched off and hide point clouds on every old link. Adding it needs a
37
+ // format version that can tell "absent" from "false".
38
+
33
39
  function getPath(obj, path) {
34
40
  return path.split(".").reduce((o, k) => (o && typeof o === "object" ? o[k] : undefined), obj);
35
41
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simview
3
- Version: 4.2.0
3
+ Version: 4.2.1
4
4
  Summary: THREE.js-based simulation visualization tool
5
5
  Author-email: Jan Vlk <vlkjan6@fel.cvut.cz>, Ales Kucera <kuceral4@fel.cvut.cz>, David Korcak <david.korcak@gmail.com>
6
6
  License-Expression: BSD-3-Clause
@@ -56,6 +56,7 @@ simview/static/js/utils/batchVisibility.js
56
56
  simview/static/js/utils/blobCodec.js
57
57
  simview/static/js/utils/blobWindow.js
58
58
  simview/static/js/utils/bodyTransforms.js
59
+ simview/static/js/utils/cameraRange.js
59
60
  simview/static/js/utils/csv.js
60
61
  simview/static/js/utils/episodes.js
61
62
  simview/static/js/utils/errorMath.js
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes