matterviz 0.3.7 → 0.4.1

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 (486) hide show
  1. package/dist/Icon.svelte +7 -4
  2. package/dist/MillerIndexInput.svelte +1 -1
  3. package/dist/api/optimade.js +32 -26
  4. package/dist/app.css +0 -3
  5. package/dist/brillouin/BrillouinZone.svelte +76 -148
  6. package/dist/brillouin/BrillouinZone.svelte.d.ts +6 -14
  7. package/dist/brillouin/BrillouinZoneExportPane.svelte +43 -96
  8. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  9. package/dist/brillouin/BrillouinZoneInfoPane.svelte +9 -32
  10. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
  11. package/dist/brillouin/BrillouinZoneScene.svelte +97 -205
  12. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +4 -23
  13. package/dist/brillouin/BrillouinZoneTooltip.svelte +16 -25
  14. package/dist/brillouin/ReciprocalVectors.svelte +39 -0
  15. package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
  16. package/dist/brillouin/compute.d.ts +2 -0
  17. package/dist/brillouin/compute.js +89 -90
  18. package/dist/brillouin/geometry.d.ts +8 -0
  19. package/dist/brillouin/geometry.js +57 -0
  20. package/dist/brillouin/index.d.ts +2 -0
  21. package/dist/brillouin/index.js +2 -0
  22. package/dist/brillouin/types.d.ts +2 -2
  23. package/dist/chempot-diagram/ChemPotDiagram.svelte +14 -13
  24. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
  25. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +109 -203
  26. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
  27. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +180 -470
  28. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
  29. package/dist/chempot-diagram/async-compute.svelte.js +3 -1
  30. package/dist/chempot-diagram/chempot-worker.js +2 -1
  31. package/dist/chempot-diagram/color.d.ts +3 -6
  32. package/dist/chempot-diagram/color.js +5 -5
  33. package/dist/chempot-diagram/compute.d.ts +4 -4
  34. package/dist/chempot-diagram/compute.js +20 -20
  35. package/dist/chempot-diagram/controls-state.svelte.d.ts +10 -0
  36. package/dist/chempot-diagram/controls-state.svelte.js +42 -0
  37. package/dist/chempot-diagram/export.d.ts +47 -0
  38. package/dist/chempot-diagram/export.js +133 -0
  39. package/dist/chempot-diagram/index.d.ts +1 -0
  40. package/dist/chempot-diagram/index.js +1 -0
  41. package/dist/chempot-diagram/pointer.d.ts +0 -10
  42. package/dist/chempot-diagram/pointer.js +4 -4
  43. package/dist/chempot-diagram/types.d.ts +3 -3
  44. package/dist/colors/index.js +8 -7
  45. package/dist/composition/FormulaFilter.svelte +18 -11
  46. package/dist/composition/PieChart.svelte +11 -10
  47. package/dist/composition/chem-sys.d.ts +8 -0
  48. package/dist/composition/chem-sys.js +86 -0
  49. package/dist/composition/format.js +7 -4
  50. package/dist/composition/index.d.ts +1 -0
  51. package/dist/composition/index.js +1 -0
  52. package/dist/composition/parse.d.ts +0 -1
  53. package/dist/composition/parse.js +41 -31
  54. package/dist/controls.d.ts +1 -0
  55. package/dist/controls.js +0 -1
  56. package/dist/convex-hull/ConvexHull.svelte +8 -10
  57. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
  58. package/dist/convex-hull/ConvexHull2D.svelte +106 -185
  59. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  60. package/dist/convex-hull/ConvexHull3D.svelte +179 -683
  61. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  62. package/dist/convex-hull/ConvexHull4D.svelte +183 -687
  63. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  64. package/dist/convex-hull/ConvexHullChrome.svelte +268 -0
  65. package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
  66. package/dist/convex-hull/ConvexHullControls.svelte +88 -7
  67. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
  68. package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
  69. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
  70. package/dist/convex-hull/ConvexHullStats.svelte +36 -175
  71. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
  72. package/dist/convex-hull/ConvexHullTooltip.svelte +11 -2
  73. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
  74. package/dist/convex-hull/GasPressureControls.svelte +4 -4
  75. package/dist/convex-hull/TemperatureSlider.svelte +2 -2
  76. package/dist/convex-hull/barycentric-coords.d.ts +2 -4
  77. package/dist/convex-hull/barycentric-coords.js +6 -33
  78. package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
  79. package/dist/convex-hull/canvas-interactions.svelte.js +278 -0
  80. package/dist/convex-hull/demo-temperature.d.ts +1 -1
  81. package/dist/convex-hull/demo-temperature.js +20 -22
  82. package/dist/convex-hull/gas-thermodynamics.d.ts +2 -2
  83. package/dist/convex-hull/gas-thermodynamics.js +22 -30
  84. package/dist/convex-hull/helpers.d.ts +42 -7
  85. package/dist/convex-hull/helpers.js +171 -78
  86. package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
  87. package/dist/convex-hull/hull-state.svelte.js +124 -0
  88. package/dist/convex-hull/index.d.ts +10 -8
  89. package/dist/convex-hull/index.js +7 -2
  90. package/dist/convex-hull/thermodynamics.js +136 -960
  91. package/dist/convex-hull/types.d.ts +13 -5
  92. package/dist/convex-hull/types.js +12 -0
  93. package/dist/coordination/CoordinationBarPlot.svelte +27 -34
  94. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  95. package/dist/element/BohrAtom.svelte +2 -1
  96. package/dist/element/index.d.ts +4 -0
  97. package/dist/element/index.js +18 -0
  98. package/dist/feedback/DragOverlay.svelte +3 -1
  99. package/dist/feedback/DragOverlay.svelte.d.ts +1 -0
  100. package/dist/feedback/StatusMessage.svelte +13 -3
  101. package/dist/fermi-surface/FermiSlice.svelte +13 -5
  102. package/dist/fermi-surface/FermiSurface.svelte +78 -151
  103. package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -14
  104. package/dist/fermi-surface/FermiSurfaceControls.svelte +1 -1
  105. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  106. package/dist/fermi-surface/FermiSurfaceScene.svelte +72 -221
  107. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
  108. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +8 -34
  109. package/dist/fermi-surface/compute.js +67 -66
  110. package/dist/fermi-surface/export.js +6 -16
  111. package/dist/fermi-surface/index.d.ts +0 -1
  112. package/dist/fermi-surface/index.js +0 -1
  113. package/dist/fermi-surface/parse.d.ts +1 -1
  114. package/dist/fermi-surface/parse.js +71 -79
  115. package/dist/fermi-surface/types.d.ts +3 -2
  116. package/dist/heatmap-matrix/HeatmapMatrix.svelte +69 -52
  117. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +4 -3
  118. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +3 -2
  119. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
  120. package/dist/heatmap-matrix/index.d.ts +3 -2
  121. package/dist/heatmap-matrix/index.js +1 -1
  122. package/dist/index.d.ts +1 -0
  123. package/dist/index.js +1 -0
  124. package/dist/io/ExportPane.svelte +166 -0
  125. package/dist/io/ExportPane.svelte.d.ts +17 -0
  126. package/dist/io/decompress.js +5 -4
  127. package/dist/io/export.d.ts +9 -5
  128. package/dist/io/export.js +77 -51
  129. package/dist/io/fetch.d.ts +2 -1
  130. package/dist/io/fetch.js +5 -1
  131. package/dist/io/file-drop.d.ts +8 -1
  132. package/dist/io/file-drop.js +48 -36
  133. package/dist/io/index.d.ts +2 -0
  134. package/dist/io/index.js +10 -0
  135. package/dist/io/types.d.ts +13 -0
  136. package/dist/io/url-drop.js +64 -33
  137. package/dist/isosurface/parse.js +52 -51
  138. package/dist/isosurface/slice.js +5 -4
  139. package/dist/isosurface/types.js +1 -1
  140. package/dist/keyboard.d.ts +3 -0
  141. package/dist/keyboard.js +23 -0
  142. package/dist/labels.d.ts +1 -1
  143. package/dist/labels.js +9 -8
  144. package/dist/layout/FullscreenButton.svelte +33 -0
  145. package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
  146. package/dist/layout/FullscreenToggle.svelte +8 -14
  147. package/dist/layout/PropertyFilter.svelte +3 -2
  148. package/dist/layout/SettingsSection.svelte +1 -1
  149. package/dist/layout/ViewerChrome.svelte +116 -0
  150. package/dist/layout/ViewerChrome.svelte.d.ts +17 -0
  151. package/dist/layout/fullscreen.d.ts +4 -0
  152. package/dist/layout/fullscreen.svelte.d.ts +8 -0
  153. package/dist/layout/fullscreen.svelte.js +37 -0
  154. package/dist/layout/index.d.ts +3 -0
  155. package/dist/layout/index.js +3 -0
  156. package/dist/layout/json-tree/JsonNode.svelte +1 -1
  157. package/dist/layout/json-tree/JsonTree.svelte +2 -2
  158. package/dist/layout/json-tree/utils.js +5 -4
  159. package/dist/marching-cubes.js +8 -13
  160. package/dist/math.d.ts +12 -4
  161. package/dist/math.js +42 -30
  162. package/dist/overlays/DraggablePane.svelte +4 -4
  163. package/dist/overlays/index.d.ts +4 -0
  164. package/dist/periodic-table/PeriodicTable.svelte +27 -15
  165. package/dist/periodic-table/PropertySelect.svelte +1 -0
  166. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +9 -3
  167. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  168. package/dist/phase-diagram/PhaseDiagramControls.svelte +3 -2
  169. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
  170. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +4 -2
  171. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
  172. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +47 -132
  173. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
  174. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +1 -1
  175. package/dist/phase-diagram/build-diagram.js +2 -2
  176. package/dist/phase-diagram/colors.js +1 -1
  177. package/dist/phase-diagram/parse.d.ts +2 -1
  178. package/dist/phase-diagram/parse.js +6 -5
  179. package/dist/phase-diagram/types.d.ts +1 -1
  180. package/dist/phase-diagram/utils.d.ts +3 -3
  181. package/dist/phase-diagram/utils.js +8 -12
  182. package/dist/plot/{BarPlot.svelte → bar/BarPlot.svelte} +246 -841
  183. package/dist/plot/{BarPlot.svelte.d.ts → bar/BarPlot.svelte.d.ts} +8 -16
  184. package/dist/plot/{BarPlotControls.svelte → bar/BarPlotControls.svelte} +6 -5
  185. package/dist/plot/{BarPlotControls.svelte.d.ts → bar/BarPlotControls.svelte.d.ts} +3 -3
  186. package/dist/plot/{SpacegroupBarPlot.svelte → bar/SpacegroupBarPlot.svelte} +8 -7
  187. package/dist/plot/{SpacegroupBarPlot.svelte.d.ts → bar/SpacegroupBarPlot.svelte.d.ts} +1 -1
  188. package/dist/plot/bar/data.d.ts +40 -0
  189. package/dist/plot/bar/data.js +154 -0
  190. package/dist/plot/bar/geometry.d.ts +39 -0
  191. package/dist/plot/bar/geometry.js +60 -0
  192. package/dist/plot/bar/index.d.ts +3 -0
  193. package/dist/plot/bar/index.js +3 -0
  194. package/dist/plot/box/BoxPlot.svelte +1292 -0
  195. package/dist/plot/box/BoxPlot.svelte.d.ts +95 -0
  196. package/dist/plot/box/BoxPlotControls.svelte +109 -0
  197. package/dist/plot/box/BoxPlotControls.svelte.d.ts +19 -0
  198. package/dist/plot/box/Violin.svelte +14 -0
  199. package/dist/plot/box/Violin.svelte.d.ts +70 -0
  200. package/dist/plot/box/box-plot.d.ts +56 -0
  201. package/dist/plot/box/box-plot.js +129 -0
  202. package/dist/plot/box/index.d.ts +5 -0
  203. package/dist/plot/box/index.js +5 -0
  204. package/dist/plot/box/kde.d.ts +17 -0
  205. package/dist/plot/box/kde.js +160 -0
  206. package/dist/plot/box/quantile.d.ts +3 -0
  207. package/dist/plot/box/quantile.js +53 -0
  208. package/dist/plot/{auto-place.d.ts → core/auto-place.d.ts} +1 -1
  209. package/dist/plot/{auto-place.js → core/auto-place.js} +6 -3
  210. package/dist/plot/core/axis-utils.d.ts +46 -0
  211. package/dist/plot/core/axis-utils.js +110 -0
  212. package/dist/plot/{AxisLabel.svelte → core/components/AxisLabel.svelte} +2 -2
  213. package/dist/plot/{AxisLabel.svelte.d.ts → core/components/AxisLabel.svelte.d.ts} +1 -1
  214. package/dist/plot/{ColorBar.svelte → core/components/ColorBar.svelte} +41 -38
  215. package/dist/plot/{ColorBar.svelte.d.ts → core/components/ColorBar.svelte.d.ts} +7 -6
  216. package/dist/plot/{ColorScaleSelect.svelte → core/components/ColorScaleSelect.svelte} +4 -3
  217. package/dist/plot/{ColorScaleSelect.svelte.d.ts → core/components/ColorScaleSelect.svelte.d.ts} +2 -2
  218. package/dist/plot/core/components/ControlPane.svelte +46 -0
  219. package/dist/plot/core/components/ControlPane.svelte.d.ts +13 -0
  220. package/dist/plot/{FillArea.svelte → core/components/FillArea.svelte} +17 -6
  221. package/dist/plot/{FillArea.svelte.d.ts → core/components/FillArea.svelte.d.ts} +1 -1
  222. package/dist/plot/{InteractiveAxisLabel.svelte → core/components/InteractiveAxisLabel.svelte} +3 -3
  223. package/dist/plot/{InteractiveAxisLabel.svelte.d.ts → core/components/InteractiveAxisLabel.svelte.d.ts} +2 -2
  224. package/dist/plot/{Line.svelte → core/components/Line.svelte} +33 -15
  225. package/dist/plot/{Line.svelte.d.ts → core/components/Line.svelte.d.ts} +3 -2
  226. package/dist/plot/{PlotAxis.svelte → core/components/PlotAxis.svelte} +9 -6
  227. package/dist/plot/{PlotAxis.svelte.d.ts → core/components/PlotAxis.svelte.d.ts} +5 -3
  228. package/dist/plot/{PlotControls.svelte → core/components/PlotControls.svelte} +17 -29
  229. package/dist/plot/core/components/PlotControls.svelte.d.ts +4 -0
  230. package/dist/plot/{PlotLegend.svelte → core/components/PlotLegend.svelte} +21 -10
  231. package/dist/plot/{PlotLegend.svelte.d.ts → core/components/PlotLegend.svelte.d.ts} +3 -2
  232. package/dist/plot/{PlotTooltip.svelte → core/components/PlotTooltip.svelte} +17 -1
  233. package/dist/plot/{PlotTooltip.svelte.d.ts → core/components/PlotTooltip.svelte.d.ts} +8 -0
  234. package/dist/plot/{PortalSelect.svelte → core/components/PortalSelect.svelte} +11 -7
  235. package/dist/plot/{ReferenceLine.svelte → core/components/ReferenceLine.svelte} +3 -3
  236. package/dist/plot/{ReferenceLine.svelte.d.ts → core/components/ReferenceLine.svelte.d.ts} +1 -1
  237. package/dist/plot/{ReferenceLine3D.svelte → core/components/ReferenceLine3D.svelte} +5 -5
  238. package/dist/plot/{ReferenceLine3D.svelte.d.ts → core/components/ReferenceLine3D.svelte.d.ts} +5 -5
  239. package/dist/plot/{ReferencePlane.svelte → core/components/ReferencePlane.svelte} +8 -8
  240. package/dist/plot/{ReferencePlane.svelte.d.ts → core/components/ReferencePlane.svelte.d.ts} +5 -5
  241. package/dist/plot/{ZeroLines.svelte → core/components/ZeroLines.svelte} +3 -3
  242. package/dist/plot/{ZeroLines.svelte.d.ts → core/components/ZeroLines.svelte.d.ts} +3 -3
  243. package/dist/plot/{ZoomRect.svelte → core/components/ZoomRect.svelte} +1 -1
  244. package/dist/plot/{ZoomRect.svelte.d.ts → core/components/ZoomRect.svelte.d.ts} +1 -1
  245. package/dist/plot/core/components/index.d.ts +17 -0
  246. package/dist/plot/core/components/index.js +17 -0
  247. package/dist/plot/{data-cleaning.d.ts → core/data-cleaning.d.ts} +71 -1
  248. package/dist/plot/{data-cleaning.js → core/data-cleaning.js} +21 -23
  249. package/dist/plot/{data-transform.d.ts → core/data-transform.d.ts} +2 -2
  250. package/dist/plot/{data-transform.js → core/data-transform.js} +3 -3
  251. package/dist/plot/core/fill-utils.d.ts +34 -0
  252. package/dist/plot/core/fill-utils.js +391 -0
  253. package/dist/plot/core/index.d.ts +10 -0
  254. package/dist/plot/core/index.js +11 -0
  255. package/dist/plot/core/interactions.d.ts +39 -0
  256. package/dist/plot/core/interactions.js +209 -0
  257. package/dist/plot/{layout.d.ts → core/layout.d.ts} +1 -0
  258. package/dist/plot/{layout.js → core/layout.js} +16 -8
  259. package/dist/plot/core/pan-zoom.svelte.d.ts +35 -0
  260. package/dist/plot/core/pan-zoom.svelte.js +221 -0
  261. package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
  262. package/dist/plot/core/placed-tween.svelte.js +68 -0
  263. package/dist/plot/{reference-line.d.ts → core/reference-line.d.ts} +11 -11
  264. package/dist/plot/{reference-line.js → core/reference-line.js} +29 -42
  265. package/dist/plot/core/scales.d.ts +40 -0
  266. package/dist/plot/{scales.js → core/scales.js} +94 -93
  267. package/dist/plot/core/svg.d.ts +3 -0
  268. package/dist/plot/core/svg.js +41 -0
  269. package/dist/plot/{types.d.ts → core/types.d.ts} +36 -85
  270. package/dist/plot/{types.js → core/types.js} +1 -1
  271. package/dist/plot/{utils → core/utils}/label-placement.d.ts +3 -3
  272. package/dist/plot/{utils → core/utils}/label-placement.js +3 -3
  273. package/dist/plot/core/utils/series-visibility.d.ts +26 -0
  274. package/dist/plot/{utils → core/utils}/series-visibility.js +29 -2
  275. package/dist/plot/core/utils.d.ts +12 -0
  276. package/dist/plot/core/utils.js +27 -0
  277. package/dist/plot/{Histogram.svelte → histogram/Histogram.svelte} +174 -551
  278. package/dist/plot/{Histogram.svelte.d.ts → histogram/Histogram.svelte.d.ts} +2 -2
  279. package/dist/plot/{HistogramControls.svelte → histogram/HistogramControls.svelte} +6 -6
  280. package/dist/plot/{HistogramControls.svelte.d.ts → histogram/HistogramControls.svelte.d.ts} +4 -4
  281. package/dist/plot/histogram/index.d.ts +2 -0
  282. package/dist/plot/histogram/index.js +2 -0
  283. package/dist/plot/index.d.ts +8 -41
  284. package/dist/plot/index.js +10 -39
  285. package/dist/plot/sankey/Sankey.svelte +697 -0
  286. package/dist/plot/sankey/Sankey.svelte.d.ts +74 -0
  287. package/dist/plot/sankey/SankeyControls.svelte +98 -0
  288. package/dist/plot/sankey/SankeyControls.svelte.d.ts +19 -0
  289. package/dist/plot/sankey/index.d.ts +4 -0
  290. package/dist/plot/sankey/index.js +3 -0
  291. package/dist/plot/sankey/sankey-types.d.ts +42 -0
  292. package/dist/plot/sankey/sankey-types.js +4 -0
  293. package/dist/plot/sankey/sankey.d.ts +52 -0
  294. package/dist/plot/sankey/sankey.js +189 -0
  295. package/dist/plot/{BinnedScatterPlot.svelte → scatter/BinnedScatterPlot.svelte} +64 -64
  296. package/dist/plot/{BinnedScatterPlot.svelte.d.ts → scatter/BinnedScatterPlot.svelte.d.ts} +6 -6
  297. package/dist/plot/{ElementScatter.svelte → scatter/ElementScatter.svelte} +6 -6
  298. package/dist/plot/{ElementScatter.svelte.d.ts → scatter/ElementScatter.svelte.d.ts} +2 -2
  299. package/dist/plot/{ScatterPlot.svelte → scatter/ScatterPlot.svelte} +297 -1008
  300. package/dist/plot/{ScatterPlot.svelte.d.ts → scatter/ScatterPlot.svelte.d.ts} +10 -18
  301. package/dist/plot/{ScatterPlotControls.svelte → scatter/ScatterPlotControls.svelte} +6 -5
  302. package/dist/plot/{ScatterPlotControls.svelte.d.ts → scatter/ScatterPlotControls.svelte.d.ts} +2 -2
  303. package/dist/plot/{ScatterPoint.svelte → scatter/ScatterPoint.svelte} +7 -7
  304. package/dist/plot/{ScatterPoint.svelte.d.ts → scatter/ScatterPoint.svelte.d.ts} +3 -3
  305. package/dist/plot/{adaptive-density.d.ts → scatter/adaptive-density.d.ts} +14 -4
  306. package/dist/plot/{adaptive-density.js → scatter/adaptive-density.js} +46 -20
  307. package/dist/plot/{binned-scatter-types.d.ts → scatter/binned-scatter-types.d.ts} +5 -12
  308. package/dist/plot/scatter/index.d.ts +7 -0
  309. package/dist/plot/scatter/index.js +5 -0
  310. package/dist/plot/scatter/scatter-data.d.ts +19 -0
  311. package/dist/plot/scatter/scatter-data.js +212 -0
  312. package/dist/plot/{ScatterPlot3D.svelte → scatter-3d/ScatterPlot3D.svelte} +25 -34
  313. package/dist/plot/{ScatterPlot3D.svelte.d.ts → scatter-3d/ScatterPlot3D.svelte.d.ts} +9 -17
  314. package/dist/plot/{ScatterPlot3DControls.svelte → scatter-3d/ScatterPlot3DControls.svelte} +14 -14
  315. package/dist/plot/{ScatterPlot3DControls.svelte.d.ts → scatter-3d/ScatterPlot3DControls.svelte.d.ts} +6 -6
  316. package/dist/plot/{ScatterPlot3DScene.svelte → scatter-3d/ScatterPlot3DScene.svelte} +129 -128
  317. package/dist/plot/{ScatterPlot3DScene.svelte.d.ts → scatter-3d/ScatterPlot3DScene.svelte.d.ts} +6 -15
  318. package/dist/plot/{Surface3D.svelte → scatter-3d/Surface3D.svelte} +7 -6
  319. package/dist/plot/{Surface3D.svelte.d.ts → scatter-3d/Surface3D.svelte.d.ts} +5 -4
  320. package/dist/plot/scatter-3d/index.d.ts +4 -0
  321. package/dist/plot/scatter-3d/index.js +4 -0
  322. package/dist/plot/sunburst/Sunburst.svelte +1041 -0
  323. package/dist/plot/sunburst/Sunburst.svelte.d.ts +97 -0
  324. package/dist/plot/sunburst/SunburstControls.svelte +200 -0
  325. package/dist/plot/sunburst/SunburstControls.svelte.d.ts +26 -0
  326. package/dist/plot/sunburst/index.d.ts +4 -0
  327. package/dist/plot/sunburst/index.js +4 -0
  328. package/dist/plot/sunburst/render.d.ts +34 -0
  329. package/dist/plot/sunburst/render.js +122 -0
  330. package/dist/plot/sunburst/sunburst.d.ts +62 -0
  331. package/dist/plot/sunburst/sunburst.js +269 -0
  332. package/dist/rdf/RdfPlot.svelte +2 -1
  333. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  334. package/dist/rdf/calc-rdf.js +11 -24
  335. package/dist/sanitize.js +14 -3
  336. package/dist/scene/SceneCamera.svelte +62 -0
  337. package/dist/scene/SceneCamera.svelte.d.ts +19 -0
  338. package/dist/scene/bind-renderer.svelte.d.ts +2 -0
  339. package/dist/scene/bind-renderer.svelte.js +14 -0
  340. package/dist/scene/index.d.ts +4 -0
  341. package/dist/scene/index.js +5 -0
  342. package/dist/scene/props.js +52 -0
  343. package/dist/scene/types.d.ts +26 -0
  344. package/dist/scene/types.js +1 -0
  345. package/dist/settings.d.ts +79 -3
  346. package/dist/settings.js +321 -1
  347. package/dist/spectral/Bands.svelte +47 -36
  348. package/dist/spectral/Bands.svelte.d.ts +6 -6
  349. package/dist/spectral/BandsAndDos.svelte +23 -25
  350. package/dist/spectral/BrillouinBandsDos.svelte +42 -30
  351. package/dist/spectral/Dos.svelte +15 -23
  352. package/dist/spectral/Dos.svelte.d.ts +4 -3
  353. package/dist/spectral/helpers.d.ts +8 -6
  354. package/dist/spectral/helpers.js +137 -65
  355. package/dist/state.svelte.d.ts +0 -7
  356. package/dist/state.svelte.js +0 -6
  357. package/dist/structure/Arrow.svelte +2 -4
  358. package/dist/structure/AtomLegend.svelte +8 -9
  359. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  360. package/dist/structure/CanvasTooltip.svelte +1 -0
  361. package/dist/structure/CellSelect.svelte +12 -5
  362. package/dist/structure/CellSelect.svelte.d.ts +2 -1
  363. package/dist/structure/Cylinder.svelte +12 -8
  364. package/dist/structure/Cylinder.svelte.d.ts +4 -1
  365. package/dist/structure/Lattice.svelte +2 -2
  366. package/dist/structure/Structure.svelte +365 -423
  367. package/dist/structure/Structure.svelte.d.ts +5 -15
  368. package/dist/structure/StructureControls.svelte +217 -2
  369. package/dist/structure/StructureControls.svelte.d.ts +5 -3
  370. package/dist/structure/StructureExportPane.svelte +54 -156
  371. package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
  372. package/dist/structure/StructureInfoPane.svelte +10 -9
  373. package/dist/structure/StructureInfoPane.svelte.d.ts +5 -5
  374. package/dist/structure/StructureScene.svelte +376 -208
  375. package/dist/structure/StructureScene.svelte.d.ts +22 -20
  376. package/dist/structure/{label-placement.d.ts → atom-label-placement.d.ts} +3 -3
  377. package/dist/structure/{label-placement.js → atom-label-placement.js} +15 -5
  378. package/dist/structure/atom-properties.d.ts +1 -1
  379. package/dist/structure/atom-properties.js +17 -22
  380. package/dist/structure/bond-order-perception.js +3 -5
  381. package/dist/structure/bonding.d.ts +4 -0
  382. package/dist/structure/bonding.js +134 -63
  383. package/dist/structure/export.d.ts +24 -4
  384. package/dist/structure/export.js +89 -143
  385. package/dist/structure/index.d.ts +4 -4
  386. package/dist/structure/index.js +3 -3
  387. package/dist/structure/measure.d.ts +3 -2
  388. package/dist/structure/measure.js +6 -5
  389. package/dist/structure/parse.d.ts +3 -2
  390. package/dist/structure/parse.js +419 -438
  391. package/dist/structure/partial-occupancy.d.ts +0 -1
  392. package/dist/structure/partial-occupancy.js +1 -1
  393. package/dist/structure/pbc.d.ts +1 -1
  394. package/dist/structure/pbc.js +190 -13
  395. package/dist/structure/polyhedra.d.ts +41 -0
  396. package/dist/structure/polyhedra.js +602 -0
  397. package/dist/structure/site.d.ts +4 -0
  398. package/dist/structure/site.js +1 -0
  399. package/dist/structure/supercell.js +3 -2
  400. package/dist/structure/validation.js +5 -6
  401. package/dist/symmetry/SymmetryElementControls.svelte +69 -0
  402. package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
  403. package/dist/symmetry/SymmetryElements.svelte +354 -0
  404. package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
  405. package/dist/symmetry/SymmetryStats.svelte +113 -8
  406. package/dist/symmetry/WyckoffTable.svelte +68 -7
  407. package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
  408. package/dist/symmetry/cell-transform.js +7 -14
  409. package/dist/symmetry/index.d.ts +14 -4
  410. package/dist/symmetry/index.js +291 -72
  411. package/dist/symmetry/spacegroups.d.ts +12 -1
  412. package/dist/symmetry/spacegroups.js +63 -14
  413. package/dist/symmetry/symmetry-elements.d.ts +33 -0
  414. package/dist/symmetry/symmetry-elements.js +521 -0
  415. package/dist/symmetry/wyckoff-db.d.ts +9 -0
  416. package/dist/symmetry/wyckoff-db.js +87 -0
  417. package/dist/table/HeatmapTable.svelte +66 -25
  418. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  419. package/dist/table/index.d.ts +1 -3
  420. package/dist/table/index.js +1 -1
  421. package/dist/theme/index.js +8 -8
  422. package/dist/tooltip/KCoords.svelte +45 -0
  423. package/dist/tooltip/KCoords.svelte.d.ts +8 -0
  424. package/dist/tooltip/index.d.ts +1 -0
  425. package/dist/tooltip/index.js +1 -0
  426. package/dist/trajectory/Trajectory.svelte +123 -100
  427. package/dist/trajectory/Trajectory.svelte.d.ts +11 -22
  428. package/dist/trajectory/TrajectoryExportPane.svelte +17 -25
  429. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
  430. package/dist/trajectory/TrajectoryInfoPane.svelte +5 -3
  431. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
  432. package/dist/trajectory/constants.js +6 -2
  433. package/dist/trajectory/extract.js +17 -37
  434. package/dist/trajectory/format-detect.d.ts +1 -1
  435. package/dist/trajectory/format-detect.js +27 -19
  436. package/dist/trajectory/frame-reader.d.ts +0 -1
  437. package/dist/trajectory/frame-reader.js +63 -162
  438. package/dist/trajectory/helpers.d.ts +10 -2
  439. package/dist/trajectory/helpers.js +56 -36
  440. package/dist/trajectory/index.js +1 -1
  441. package/dist/trajectory/parse/ase.d.ts +9 -1
  442. package/dist/trajectory/parse/ase.js +47 -32
  443. package/dist/trajectory/parse/diagnostics.d.ts +3 -0
  444. package/dist/trajectory/parse/diagnostics.js +14 -0
  445. package/dist/trajectory/parse/hdf5.js +1 -1
  446. package/dist/trajectory/parse/index.d.ts +1 -1
  447. package/dist/trajectory/parse/index.js +65 -105
  448. package/dist/trajectory/parse/lammps.d.ts +0 -2
  449. package/dist/trajectory/parse/lammps.js +8 -6
  450. package/dist/trajectory/parse/pymatgen.d.ts +2 -0
  451. package/dist/trajectory/parse/pymatgen.js +74 -0
  452. package/dist/trajectory/parse/vasp.js +38 -18
  453. package/dist/trajectory/parse/xyz.d.ts +13 -1
  454. package/dist/trajectory/parse/xyz.js +102 -94
  455. package/dist/trajectory/plotting.d.ts +1 -2
  456. package/dist/trajectory/plotting.js +16 -113
  457. package/dist/utils.d.ts +2 -0
  458. package/dist/utils.js +7 -5
  459. package/dist/xrd/XrdPlot.svelte +16 -30
  460. package/dist/xrd/broadening.d.ts +2 -1
  461. package/dist/xrd/calc-xrd.js +18 -20
  462. package/dist/xrd/index.d.ts +2 -2
  463. package/dist/xrd/parse.js +2 -2
  464. package/package.json +43 -26
  465. package/dist/element/data.json +0 -11864
  466. package/dist/fermi-surface/marching-cubes.d.ts +0 -2
  467. package/dist/fermi-surface/marching-cubes.js +0 -2
  468. package/dist/plot/PlotControls.svelte.d.ts +0 -4
  469. package/dist/plot/axis-utils.d.ts +0 -19
  470. package/dist/plot/axis-utils.js +0 -78
  471. package/dist/plot/defaults.d.ts +0 -19
  472. package/dist/plot/defaults.js +0 -9
  473. package/dist/plot/fill-utils.d.ts +0 -46
  474. package/dist/plot/fill-utils.js +0 -322
  475. package/dist/plot/hover-lock.svelte.d.ts +0 -14
  476. package/dist/plot/hover-lock.svelte.js +0 -46
  477. package/dist/plot/interactions.d.ts +0 -12
  478. package/dist/plot/interactions.js +0 -101
  479. package/dist/plot/scales.d.ts +0 -48
  480. package/dist/plot/svg.d.ts +0 -1
  481. package/dist/plot/svg.js +0 -11
  482. package/dist/plot/utils/series-visibility.d.ts +0 -15
  483. package/dist/plot/utils.d.ts +0 -1
  484. package/dist/plot/utils.js +0 -14
  485. /package/dist/plot/{PortalSelect.svelte.d.ts → core/components/PortalSelect.svelte.d.ts} +0 -0
  486. /package/dist/plot/{binned-scatter-types.js → scatter/binned-scatter-types.js} +0 -0
@@ -0,0 +1,602 @@
1
+ // Coordination polyhedra detection and mesh generation.
2
+ // Self-contained: vertices come from the rendered bond graph, hulls from a custom
3
+ // quickhull tailored to small point sets (CN 4-12), output as merged typed arrays
4
+ // so the whole scene renders in 1-2 draw calls regardless of supercell size.
5
+ // Hot paths use scalar math and per-element caches to scale to large structures.
6
+ import { rgb as parse_rgb } from 'd3-color';
7
+ import { DEFAULTS } from '../settings';
8
+ import { get_orig_site_idx } from './atom-properties';
9
+ import { element_lookup, get_majority_element } from './bonding';
10
+ const face_of = (points, vert_a, vert_b, vert_c) => {
11
+ const [ax, ay, az] = points[vert_a];
12
+ const abx = points[vert_b][0] - ax;
13
+ const aby = points[vert_b][1] - ay;
14
+ const abz = points[vert_b][2] - az;
15
+ const acx = points[vert_c][0] - ax;
16
+ const acy = points[vert_c][1] - ay;
17
+ const acz = points[vert_c][2] - az;
18
+ let nx = aby * acz - abz * acy;
19
+ let ny = abz * acx - abx * acz;
20
+ let nz = abx * acy - aby * acx;
21
+ const len = Math.hypot(nx, ny, nz);
22
+ if (len > 0) {
23
+ nx /= len;
24
+ ny /= len;
25
+ nz /= len;
26
+ }
27
+ else
28
+ [nx, ny, nz] = [0, 0, 1];
29
+ return {
30
+ vert_a,
31
+ vert_b,
32
+ vert_c,
33
+ nx,
34
+ ny,
35
+ nz,
36
+ offset: nx * ax + ny * ay + nz * az,
37
+ outside: [],
38
+ deleted: false,
39
+ };
40
+ };
41
+ // Signed distance of point from face plane (positive = outside).
42
+ const dist_to_face = (face, point) => face.nx * point[0] + face.ny * point[1] + face.nz * point[2] - face.offset;
43
+ // Compute the 3D convex hull of a small point set via quickhull.
44
+ // Returns a degenerate result (faces=[], volume=0) for <4 unique points or
45
+ // collinear/coplanar sets (e.g. square-planar CN=4 coordination draws nothing,
46
+ // matching VESTA behavior). Supports up to 65535 input points (edge keys are
47
+ // packed into 32-bit integers) - far beyond any coordination shell.
48
+ export function convex_hull_3d(points, eps_scale = 1e-7) {
49
+ // Dedup points (coordination shells are tiny, O(n^2) is fine)
50
+ const unique = [];
51
+ const unique_input_idx = [];
52
+ for (let p_idx = 0; p_idx < points.length; p_idx++) {
53
+ const [px, py, pz] = points[p_idx];
54
+ let is_dup = false;
55
+ for (const other of unique) {
56
+ const dx = px - other[0];
57
+ const dy = py - other[1];
58
+ const dz = pz - other[2];
59
+ if (dx * dx + dy * dy + dz * dz < 1e-12) {
60
+ is_dup = true;
61
+ break;
62
+ }
63
+ }
64
+ if (!is_dup) {
65
+ unique.push(points[p_idx]);
66
+ unique_input_idx.push(p_idx);
67
+ }
68
+ }
69
+ const degenerate = {
70
+ vertices: unique,
71
+ input_idxs: unique_input_idx,
72
+ faces: [],
73
+ volume: 0,
74
+ };
75
+ if (unique.length < 4)
76
+ return degenerate;
77
+ // Bounding-box diagonal sets the numerical tolerance scale
78
+ let [min_x, min_y, min_z] = unique[0];
79
+ let [max_x, max_y, max_z] = unique[0];
80
+ for (const [px, py, pz] of unique) {
81
+ if (px < min_x)
82
+ min_x = px;
83
+ if (px > max_x)
84
+ max_x = px;
85
+ if (py < min_y)
86
+ min_y = py;
87
+ if (py > max_y)
88
+ max_y = py;
89
+ if (pz < min_z)
90
+ min_z = pz;
91
+ if (pz > max_z)
92
+ max_z = pz;
93
+ }
94
+ const diag = Math.hypot(max_x - min_x, max_y - min_y, max_z - min_z);
95
+ const eps = eps_scale * Math.max(1, diag);
96
+ // Initial simplex: farthest pair along principal axes -> farthest from line -> from plane
97
+ let [pt_0, pt_1] = [0, 1];
98
+ let max_dist = -1;
99
+ for (let axis = 0; axis < 3; axis++) {
100
+ let [lo_idx, hi_idx] = [0, 0];
101
+ for (let idx = 1; idx < unique.length; idx++) {
102
+ if (unique[idx][axis] < unique[lo_idx][axis])
103
+ lo_idx = idx;
104
+ if (unique[idx][axis] > unique[hi_idx][axis])
105
+ hi_idx = idx;
106
+ }
107
+ const dx = unique[hi_idx][0] - unique[lo_idx][0];
108
+ const dy = unique[hi_idx][1] - unique[lo_idx][1];
109
+ const dz = unique[hi_idx][2] - unique[lo_idx][2];
110
+ const dist = Math.hypot(dx, dy, dz);
111
+ if (dist > max_dist)
112
+ [max_dist, pt_0, pt_1] = [dist, lo_idx, hi_idx];
113
+ }
114
+ if (max_dist < eps)
115
+ return degenerate; // all points coincide
116
+ const [ox, oy, oz] = unique[pt_0];
117
+ let dir_x = unique[pt_1][0] - ox;
118
+ let dir_y = unique[pt_1][1] - oy;
119
+ let dir_z = unique[pt_1][2] - oz;
120
+ const dir_len = Math.hypot(dir_x, dir_y, dir_z);
121
+ dir_x /= dir_len;
122
+ dir_y /= dir_len;
123
+ dir_z /= dir_len;
124
+ let pt_2 = -1;
125
+ max_dist = eps;
126
+ for (let idx = 0; idx < unique.length; idx++) {
127
+ const rx = unique[idx][0] - ox;
128
+ const ry = unique[idx][1] - oy;
129
+ const rz = unique[idx][2] - oz;
130
+ const proj = rx * dir_x + ry * dir_y + rz * dir_z;
131
+ const perp_sq = rx * rx + ry * ry + rz * rz - proj * proj;
132
+ if (perp_sq > max_dist * max_dist) {
133
+ max_dist = Math.sqrt(perp_sq);
134
+ pt_2 = idx;
135
+ }
136
+ }
137
+ if (pt_2 === -1)
138
+ return degenerate; // collinear
139
+ const base = face_of(unique, pt_0, pt_1, pt_2);
140
+ let pt_3 = -1;
141
+ max_dist = eps;
142
+ for (let idx = 0; idx < unique.length; idx++) {
143
+ const dist = Math.abs(dist_to_face(base, unique[idx]));
144
+ if (dist > max_dist)
145
+ [max_dist, pt_3] = [dist, idx];
146
+ }
147
+ if (pt_3 === -1)
148
+ return degenerate; // coplanar
149
+ // Build initial tetrahedron with outward-facing windings
150
+ const centroid = [
151
+ (unique[pt_0][0] + unique[pt_1][0] + unique[pt_2][0] + unique[pt_3][0]) / 4,
152
+ (unique[pt_0][1] + unique[pt_1][1] + unique[pt_2][1] + unique[pt_3][1]) / 4,
153
+ (unique[pt_0][2] + unique[pt_1][2] + unique[pt_2][2] + unique[pt_3][2]) / 4,
154
+ ];
155
+ const faces = [];
156
+ for (const [idx_a, idx_b, idx_c] of [
157
+ [pt_0, pt_1, pt_2],
158
+ [pt_0, pt_1, pt_3],
159
+ [pt_0, pt_2, pt_3],
160
+ [pt_1, pt_2, pt_3],
161
+ ]) {
162
+ let face = face_of(unique, idx_a, idx_b, idx_c);
163
+ if (dist_to_face(face, centroid) > 0)
164
+ face = face_of(unique, idx_a, idx_c, idx_b);
165
+ faces.push(face);
166
+ }
167
+ // Assign each remaining point to the face it lies farthest outside of
168
+ const assign_point = (point_idx, candidates) => {
169
+ let [best_face, best_dist] = [null, eps];
170
+ for (const face of candidates) {
171
+ if (face.deleted)
172
+ continue;
173
+ const dist = dist_to_face(face, unique[point_idx]);
174
+ if (dist > best_dist)
175
+ [best_face, best_dist] = [face, dist];
176
+ }
177
+ best_face?.outside.push(point_idx);
178
+ };
179
+ for (let idx = 0; idx < unique.length; idx++) {
180
+ if (idx !== pt_0 && idx !== pt_1 && idx !== pt_2 && idx !== pt_3) {
181
+ assign_point(idx, faces);
182
+ }
183
+ }
184
+ // Expand hull: repeatedly absorb the farthest outside point. Horizon edges are
185
+ // tracked as packed 32-bit integers (from * 2^16 + to) instead of strings.
186
+ const edge_set = new Set(); // packed directed edges
187
+ for (let guard = 0; guard < unique.length * 4; guard++) {
188
+ const active = faces.find((face) => !face.deleted && face.outside.length > 0);
189
+ if (!active)
190
+ break;
191
+ let [eye, eye_dist] = [-1, -Infinity];
192
+ for (const point_idx of active.outside) {
193
+ const dist = dist_to_face(active, unique[point_idx]);
194
+ if (dist > eye_dist)
195
+ [eye, eye_dist] = [point_idx, dist];
196
+ }
197
+ // Find all faces visible from the eye point and collect orphaned points
198
+ const orphans = [];
199
+ edge_set.clear();
200
+ for (const face of faces) {
201
+ if (face.deleted || dist_to_face(face, unique[eye]) <= eps)
202
+ continue;
203
+ face.deleted = true;
204
+ for (const point_idx of face.outside)
205
+ if (point_idx !== eye)
206
+ orphans.push(point_idx);
207
+ for (const [from, to] of [
208
+ [face.vert_a, face.vert_b],
209
+ [face.vert_b, face.vert_c],
210
+ [face.vert_c, face.vert_a],
211
+ ]) {
212
+ const reverse_key = to * 65536 + from;
213
+ if (edge_set.has(reverse_key))
214
+ edge_set.delete(reverse_key); // internal edge
215
+ else
216
+ edge_set.add(from * 65536 + to);
217
+ }
218
+ }
219
+ // Horizon edges (directed, so new faces inherit outward winding)
220
+ const new_faces = [];
221
+ for (const packed of edge_set) {
222
+ const from = Math.floor(packed / 65536);
223
+ const to = packed % 65536;
224
+ const face = face_of(unique, from, to, eye);
225
+ faces.push(face);
226
+ new_faces.push(face);
227
+ }
228
+ for (const point_idx of orphans)
229
+ assign_point(point_idx, new_faces);
230
+ }
231
+ // Compact vertices used by surviving faces and remap indices
232
+ const vert_remap = new Map();
233
+ const vertices = [];
234
+ const input_idxs = [];
235
+ const remap = (old_idx) => {
236
+ let new_idx = vert_remap.get(old_idx);
237
+ if (new_idx === undefined) {
238
+ new_idx = vertices.length;
239
+ vert_remap.set(old_idx, new_idx);
240
+ vertices.push(unique[old_idx]);
241
+ input_idxs.push(unique_input_idx[old_idx]);
242
+ }
243
+ return new_idx;
244
+ };
245
+ const remapped = [];
246
+ for (const face of faces) {
247
+ if (!face.deleted) {
248
+ remapped.push([remap(face.vert_a), remap(face.vert_b), remap(face.vert_c)]);
249
+ }
250
+ }
251
+ // Volume via signed tetrahedra from the hull centroid (positive with outward winding)
252
+ let [cx, cy, cz] = [0, 0, 0];
253
+ for (const [vx, vy, vz] of vertices) {
254
+ cx += vx;
255
+ cy += vy;
256
+ cz += vz;
257
+ }
258
+ cx /= vertices.length;
259
+ cy /= vertices.length;
260
+ cz /= vertices.length;
261
+ let volume = 0;
262
+ for (const [idx_a, idx_b, idx_c] of remapped) {
263
+ const ax = vertices[idx_a][0] - cx;
264
+ const ay = vertices[idx_a][1] - cy;
265
+ const az = vertices[idx_a][2] - cz;
266
+ const bx = vertices[idx_b][0] - cx;
267
+ const by = vertices[idx_b][1] - cy;
268
+ const bz = vertices[idx_b][2] - cz;
269
+ const dx = vertices[idx_c][0] - cx;
270
+ const dy = vertices[idx_c][1] - cy;
271
+ const dz = vertices[idx_c][2] - cz;
272
+ volume +=
273
+ (ax * (by * dz - bz * dy) + ay * (bz * dx - bx * dz) + az * (bx * dy - by * dx)) / 6;
274
+ }
275
+ return { vertices, input_idxs, faces: remapped, volume: Math.abs(volume) };
276
+ }
277
+ // --- Bond graph adjacency ---
278
+ // Symmetric site_idx -> neighbor site_idx set from rendered bond pairs.
279
+ export function build_adjacency(bonds) {
280
+ const adjacency = new Map();
281
+ const link = (from, to) => {
282
+ const neighbors = adjacency.get(from);
283
+ if (neighbors)
284
+ neighbors.add(to);
285
+ else
286
+ adjacency.set(from, new Set([to]));
287
+ };
288
+ for (const { site_idx_1, site_idx_2 } of bonds) {
289
+ if (site_idx_1 === site_idx_2)
290
+ continue;
291
+ link(site_idx_1, site_idx_2);
292
+ link(site_idx_2, site_idx_1);
293
+ }
294
+ return adjacency;
295
+ }
296
+ // --- Center selection ---
297
+ // Large low-valent A-site cations whose coordination polyhedra (CN 8-12) tend to
298
+ // obscure the structural framework. VESTA-style figures draw the framework
299
+ // (e.g. TiO6 in BaTiO3, FeO6/PO4 in LiFePO4) and leave these as plain spheres.
300
+ // They still get polyhedra when they are the only qualifying cations (e.g. NaCl)
301
+ // or when force-included via `included_center_elements`.
302
+ const SPECTATOR_CATEGORIES = new Set([`alkali metal`]);
303
+ const HEAVY_ALKALINE_EARTHS = new Set([`Ca`, `Sr`, `Ba`, `Ra`]);
304
+ export const is_spectator_center = (element) => SPECTATOR_CATEGORIES.has(element_lookup.get(element)?.category ?? ``) ||
305
+ HEAVY_ALKALINE_EARTHS.has(element);
306
+ // A bonded neighbor counts as a polyhedron vertex only if it's an anion-former:
307
+ // a nonmetal or metalloid that is more electronegative than the center. This keeps
308
+ // spurious cation-cation bonds (e.g. Ti-Ba in perovskites, Li-P in thiophosphates)
309
+ // from contaminating coordination environments.
310
+ function is_anion_vertex(center_en, center_is_metal, neighbor_element, electronegativity_margin) {
311
+ if (!neighbor_element)
312
+ return false;
313
+ const n_data = element_lookup.get(neighbor_element);
314
+ if (n_data?.metal)
315
+ return false;
316
+ const n_en = n_data?.electronegativity ?? null;
317
+ if (center_en !== null && n_en !== null) {
318
+ return n_en > center_en + electronegativity_margin;
319
+ }
320
+ // EN data missing: only metal centers with nonmetal neighbors qualify
321
+ return center_is_metal && n_data?.nonmetal === true;
322
+ }
323
+ // --- Top-level polyhedra computation ---
324
+ // Detect coordination polyhedra from the rendered bond graph, VESTA-style:
325
+ // vertices are anion-former neighbors (nonmetals/metalloids more electronegative
326
+ // than the center) within `1 + distance_factor` of the shortest such bond, so
327
+ // over-long bond-graph noise doesn't inflate e.g. PO4 tetrahedra. Spectator A-site
328
+ // cations (alkali, heavy alkaline-earth) are skipped when framework cations exist,
329
+ // CN > max_neighbors hulls (e.g. CN-12 cuboctahedra) are skipped, and
330
+ // boundary-truncated copies only render when their vertex count matches the max
331
+ // among all copies of the same original site. Every polyhedron corner is a
332
+ // displayed atom (boundary shells are completed upstream by bond-completing image
333
+ // atoms - see find_image_atoms in pbc.ts).
334
+ export function compute_polyhedra(structure, bonds, options = {}) {
335
+ const {
336
+ // Neighbor-count fallbacks derive from DEFAULTS.structure so they can't drift
337
+ // from the polyhedra_min/max_neighbors settings defaults
338
+ min_neighbors = DEFAULTS.structure.polyhedra_min_neighbors, max_neighbors = DEFAULTS.structure.polyhedra_max_neighbors, excluded_center_elements = [], included_center_elements = [], electronegativity_margin = 0, distance_factor = 0.3, weak_bond_norm = 1.15, volume_eps = 1e-3, } = options;
339
+ const sites = structure?.sites;
340
+ if (!sites?.length || bonds.length === 0)
341
+ return [];
342
+ const adjacency = build_adjacency(bonds);
343
+ const excluded = new Set(excluded_center_elements);
344
+ const included = new Set(included_center_elements);
345
+ const site_elements = sites.map((site) => get_majority_element(site));
346
+ const unique_elements = [
347
+ ...new Set(site_elements.filter((el) => el !== null)),
348
+ ];
349
+ const center_info_cache = new Map();
350
+ const center_info = (element) => {
351
+ let info = center_info_cache.get(element);
352
+ if (!info) {
353
+ const data = element_lookup.get(element);
354
+ const center_en = data?.electronegativity ?? null;
355
+ const r_center = data?.covalent_radius ?? null;
356
+ const accepts = new Set(unique_elements.filter((n_elem) => is_anion_vertex(center_en, data?.metal === true, n_elem, electronegativity_margin)));
357
+ const radii_sums = new Map(unique_elements.map((n_elem) => {
358
+ const r_n = element_lookup.get(n_elem)?.covalent_radius ?? null;
359
+ return [n_elem, r_center !== null && r_n !== null ? r_center + r_n : null];
360
+ }));
361
+ info = { accepts, radii_sums };
362
+ center_info_cache.set(element, info);
363
+ }
364
+ return info;
365
+ };
366
+ const candidates = [];
367
+ for (const [site_idx, neighbors] of adjacency) {
368
+ if (neighbors.size < min_neighbors)
369
+ continue;
370
+ const element = site_elements[site_idx];
371
+ if (!element || excluded.has(element))
372
+ continue;
373
+ const { accepts, radii_sums } = center_info(element);
374
+ if (accepts.size === 0)
375
+ continue;
376
+ const [cx, cy, cz] = sites[site_idx].xyz;
377
+ // Bonded anion vertices (parallel arrays to avoid per-vertex object churn)
378
+ const vert_idxs = [];
379
+ const vert_dists = [];
380
+ let min_dist = Infinity;
381
+ for (const idx of neighbors) {
382
+ const n_elem = site_elements[idx];
383
+ if (!n_elem || !accepts.has(n_elem))
384
+ continue;
385
+ const [nx, ny, nz] = sites[idx].xyz;
386
+ const dist = Math.hypot(nx - cx, ny - cy, nz - cz);
387
+ vert_idxs.push(idx);
388
+ vert_dists.push(dist);
389
+ if (dist < min_dist)
390
+ min_dist = dist;
391
+ }
392
+ if (vert_idxs.length < min_neighbors)
393
+ continue;
394
+ // Trim over-long bonds relative to the shortest anion bond (VESTA-like local
395
+ // cutoff): keeps distorted/Jahn-Teller octahedra intact but rejects e.g. a 5th
396
+ // oxygen at 2.5 Å around P whose true tetrahedron has 1.5 Å bonds
397
+ const cutoff = min_dist * (1 + distance_factor);
398
+ const vertex_site_idxs = [];
399
+ let [norm_sum, norm_count] = [0, 0];
400
+ for (let pos = 0; pos < vert_idxs.length; pos++) {
401
+ if (vert_dists[pos] > cutoff)
402
+ continue;
403
+ const idx = vert_idxs[pos];
404
+ vertex_site_idxs.push(idx);
405
+ // Bond softness: how stretched the kept bonds are vs the covalent-radii sum
406
+ const n_elem = site_elements[idx];
407
+ const r_sum = n_elem ? (radii_sums.get(n_elem) ?? null) : null;
408
+ if (r_sum !== null) {
409
+ norm_sum += vert_dists[pos] / r_sum;
410
+ norm_count++;
411
+ }
412
+ }
413
+ if (vertex_site_idxs.length < min_neighbors)
414
+ continue;
415
+ candidates.push({
416
+ site_idx,
417
+ orig_idx: get_orig_site_idx(sites[site_idx], site_idx),
418
+ element,
419
+ vertex_site_idxs,
420
+ mean_norm_dist: norm_count > 0 ? norm_sum / norm_count : null,
421
+ });
422
+ }
423
+ // Pass 2: hide spectator A-site cations when the composition contains a
424
+ // potential framework cation (a non-spectator element less electronegative than
425
+ // the structure's most electronegative element, i.e. one that could coordinate
426
+ // the anions). Composition-based rather than candidate-based so boundary
427
+ // truncation of framework polyhedra doesn't promote Li/Na/Ba clutter; purely
428
+ // ionic binaries like NaCl or CaF2 still draw their spectator polyhedra.
429
+ const max_en = Math.max(...unique_elements.map((el) => element_lookup.get(el)?.electronegativity ?? -Infinity));
430
+ const has_framework_potential = unique_elements.some((el) => {
431
+ if (is_spectator_center(el))
432
+ return false;
433
+ const en = element_lookup.get(el)?.electronegativity;
434
+ return en !== null && en !== undefined && en < max_en;
435
+ });
436
+ // Weakly-bound center species (mean bond length well beyond the covalent-radii
437
+ // sum, e.g. lone-pair Bi3+ with 8 long Bi-O bonds) are hidden when a
438
+ // strongly-bound framework species exists - mirrors how pyrochlore-type figures
439
+ // show only the B-site octahedra
440
+ const norm_by_species = new Map();
441
+ for (const { element, mean_norm_dist } of candidates) {
442
+ if (mean_norm_dist === null)
443
+ continue;
444
+ const entry = norm_by_species.get(element) ?? { sum: 0, count: 0 };
445
+ entry.sum += mean_norm_dist;
446
+ entry.count++;
447
+ norm_by_species.set(element, entry);
448
+ }
449
+ const species_norm = (el) => {
450
+ const entry = norm_by_species.get(el);
451
+ return entry ? entry.sum / entry.count : null;
452
+ };
453
+ const has_strong_species = [...norm_by_species.keys()].some((el) => (species_norm(el) ?? Infinity) <= weak_bond_norm && !is_spectator_center(el));
454
+ const is_weak_species = (el) => has_strong_species && (species_norm(el) ?? 0) > weak_bond_norm;
455
+ const visible = candidates.filter(({ element }) => {
456
+ if (included.has(element))
457
+ return true;
458
+ if (is_spectator_center(element) && has_framework_potential)
459
+ return false;
460
+ return !is_weak_species(element);
461
+ });
462
+ // Pass 3: boundary completeness - copies of the same original site only render
463
+ // at the max observed vertex count, so any remaining truncated copies (bond
464
+ // completing image atoms handle most) are skipped
465
+ const max_cn_by_orig = new Map();
466
+ for (const { orig_idx, vertex_site_idxs } of visible) {
467
+ if (vertex_site_idxs.length > (max_cn_by_orig.get(orig_idx) ?? 0)) {
468
+ max_cn_by_orig.set(orig_idx, vertex_site_idxs.length);
469
+ }
470
+ }
471
+ // Pass 4: CN cap (after completeness so capped interior copies don't let
472
+ // truncated boundary copies of the same site slip through; force-included
473
+ // elements bypass the cap - an explicit user request beats the clutter
474
+ // heuristic), then build hulls, deduping identical center positions (base
475
+ // atom vs PBC image)
476
+ const polyhedra = [];
477
+ const seen_positions = new Set();
478
+ for (const { site_idx, orig_idx, element, vertex_site_idxs } of visible) {
479
+ if (vertex_site_idxs.length !== max_cn_by_orig.get(orig_idx))
480
+ continue;
481
+ if (vertex_site_idxs.length > max_neighbors && !included.has(element))
482
+ continue;
483
+ const [px, py, pz] = sites[site_idx].xyz;
484
+ const pos_key = `${Math.round(px * 1e3)},${Math.round(py * 1e3)},${Math.round(pz * 1e3)}`;
485
+ if (seen_positions.has(pos_key))
486
+ continue;
487
+ seen_positions.add(pos_key);
488
+ const hull = convex_hull_3d(vertex_site_idxs.map((idx) => sites[idx].xyz));
489
+ if (hull.faces.length === 0 || hull.volume < volume_eps)
490
+ continue;
491
+ polyhedra.push({
492
+ center_site_idx: site_idx,
493
+ center_orig_idx: orig_idx,
494
+ center_element: element,
495
+ vertices: hull.vertices,
496
+ vertex_site_idxs: hull.input_idxs.map((input_idx) => vertex_site_idxs[input_idx]),
497
+ faces: hull.faces,
498
+ volume: hull.volume,
499
+ });
500
+ }
501
+ return polyhedra;
502
+ }
503
+ // --- Merged render buffers ---
504
+ // Merge all polyhedra into single non-indexed position/color arrays (one draw call)
505
+ // plus crease-edge segments for outlines. Edges interior to coplanar face groups
506
+ // (e.g. quad diagonals on a cube) are omitted. `get_vertex_color` resolves the
507
+ // color of each hull vertex (e.g. the vertex atom's element color, the center
508
+ // atom's color, or a uniform custom color) - parsed colors are cached by string.
509
+ export function merge_polyhedra_buffers(polyhedra, get_vertex_color, coplanar_tol = 1e-3) {
510
+ let triangle_count = 0;
511
+ for (const poly of polyhedra)
512
+ triangle_count += poly.faces.length;
513
+ const positions = new Float32Array(triangle_count * 9);
514
+ const colors = new Float32Array(triangle_count * 9);
515
+ // A closed triangulated surface has at most 3F/2 unique edges
516
+ const edge_positions = new Float32Array(Math.ceil(triangle_count * 1.5) * 6);
517
+ const rgb_cache = new Map();
518
+ let offset = 0;
519
+ let edge_offset = 0;
520
+ // Per-polyhedron scratch: crease detection tracks the first face normal seen
521
+ // per undirected edge (packed vert_a * 2^16 + vert_b key)
522
+ const edge_normals = new Map();
523
+ for (const poly of polyhedra) {
524
+ const verts = poly.vertices;
525
+ // Resolve per-hull-vertex colors once
526
+ const vert_rgb = new Float32Array(verts.length * 3);
527
+ for (let v_idx = 0; v_idx < verts.length; v_idx++) {
528
+ const color = get_vertex_color(poly, v_idx);
529
+ let channels = rgb_cache.get(color);
530
+ if (!channels) {
531
+ // d3-color handles hex, rgb()/rgba() (d3 property-color scales) and named colors
532
+ const { r, g, b } = parse_rgb(color);
533
+ channels = Number.isFinite(r) ? [r / 255, g / 255, b / 255] : [0.5, 0.5, 0.5];
534
+ rgb_cache.set(color, channels);
535
+ }
536
+ vert_rgb[v_idx * 3] = channels[0];
537
+ vert_rgb[v_idx * 3 + 1] = channels[1];
538
+ vert_rgb[v_idx * 3 + 2] = channels[2];
539
+ }
540
+ edge_normals.clear();
541
+ for (const [idx_a, idx_b, idx_c] of poly.faces) {
542
+ const [ax, ay, az] = verts[idx_a];
543
+ const [bx, by, bz] = verts[idx_b];
544
+ const [px, py, pz] = verts[idx_c];
545
+ // Scalar face normal for crease detection
546
+ let nx = (by - ay) * (pz - az) - (bz - az) * (py - ay);
547
+ let ny = (bz - az) * (px - ax) - (bx - ax) * (pz - az);
548
+ let nz = (bx - ax) * (py - ay) - (by - ay) * (px - ax);
549
+ const len = Math.hypot(nx, ny, nz);
550
+ if (len > 0) {
551
+ nx /= len;
552
+ ny /= len;
553
+ nz /= len;
554
+ }
555
+ for (const v_idx of [idx_a, idx_b, idx_c]) {
556
+ const vert = verts[v_idx];
557
+ positions[offset] = vert[0];
558
+ positions[offset + 1] = vert[1];
559
+ positions[offset + 2] = vert[2];
560
+ colors[offset] = vert_rgb[v_idx * 3];
561
+ colors[offset + 1] = vert_rgb[v_idx * 3 + 1];
562
+ colors[offset + 2] = vert_rgb[v_idx * 3 + 2];
563
+ offset += 3;
564
+ }
565
+ for (const [from, to] of [
566
+ [idx_a, idx_b],
567
+ [idx_b, idx_c],
568
+ [idx_c, idx_a],
569
+ ]) {
570
+ const key = from < to ? from * 65536 + to : to * 65536 + from;
571
+ const entry = edge_normals.get(key);
572
+ if (entry) {
573
+ entry.shared = true;
574
+ entry.crease = nx * entry.nx + ny * entry.ny + nz * entry.nz < 1 - coplanar_tol;
575
+ }
576
+ else
577
+ edge_normals.set(key, { nx, ny, nz, crease: false, shared: false });
578
+ }
579
+ }
580
+ // Draw an edge unless both adjacent faces are coplanar (quad diagonal)
581
+ for (const [key, entry] of edge_normals) {
582
+ if (entry.shared && !entry.crease)
583
+ continue;
584
+ const from = verts[Math.floor(key / 65536)];
585
+ const to = verts[key % 65536];
586
+ edge_positions[edge_offset] = from[0];
587
+ edge_positions[edge_offset + 1] = from[1];
588
+ edge_positions[edge_offset + 2] = from[2];
589
+ edge_positions[edge_offset + 3] = to[0];
590
+ edge_positions[edge_offset + 4] = to[1];
591
+ edge_positions[edge_offset + 5] = to[2];
592
+ edge_offset += 6;
593
+ }
594
+ }
595
+ return {
596
+ positions,
597
+ colors,
598
+ edge_positions: edge_positions.slice(0, edge_offset),
599
+ triangle_count,
600
+ edge_count: edge_offset / 6,
601
+ };
602
+ }
@@ -0,0 +1,4 @@
1
+ import type { ElementSymbol } from '../element';
2
+ import type { Vec3 } from '../math';
3
+ import type { Site } from './';
4
+ export declare const make_site: (element: ElementSymbol, abc: Vec3, xyz: Vec3, label: string, properties?: Record<string, unknown>, occu?: number) => Site;
@@ -0,0 +1 @@
1
+ export const make_site = (element, abc, xyz, label, properties = {}, occu = 1) => ({ species: [{ element, occu, oxidation_state: 0 }], abc, xyz, label, properties });
@@ -115,7 +115,8 @@ export function make_supercell(structure, scaling, to_unit_cell = true) {
115
115
  for (let kk = 0; kk < scale_z; kk++) {
116
116
  for (let jj = 0; jj < scale_y; jj++) {
117
117
  for (let ii = 0; ii < scale_x; ii++) {
118
- const label_suffix = total_cells > 1 ? `_${ii}${jj}${kk}` : ``;
118
+ // 1x1x1 short-circuits above, so every site gets a cell-index suffix
119
+ const label_suffix = `_${ii}${jj}${kk}`;
119
120
  // Translation = ii * vec_a + jj * vec_b + kk * vec_c (inlined for performance)
120
121
  const tx = ii * ax + jj * bx + kk * cx;
121
122
  const ty = ii * ay + jj * by + kk * cy;
@@ -135,7 +136,7 @@ export function make_supercell(structure, scaling, to_unit_cell = true) {
135
136
  species: site.species,
136
137
  xyz: [site.xyz[0] + tx, site.xyz[1] + ty, site.xyz[2] + tz],
137
138
  abc: [new_a, new_b, new_c],
138
- label: label_suffix ? `${site.label}${label_suffix}` : site.label,
139
+ label: `${site.label}${label_suffix}`,
139
140
  properties: { ...site.properties, orig_unit_cell_idx: site_idx },
140
141
  };
141
142
  }
@@ -1,10 +1,9 @@
1
+ import { is_plain_object } from '../utils';
1
2
  export function is_crystal(obj) {
2
- if (obj === null || typeof obj !== `object`)
3
+ if (!is_plain_object(obj))
3
4
  return false;
4
- const structure_obj = obj;
5
- const sites = structure_obj.sites;
6
- const lattice = structure_obj.lattice;
7
- const has_sites = Array.isArray(sites) && sites.length > 0;
8
- const has_lattice = lattice !== undefined && lattice !== null && typeof lattice === `object`;
5
+ const has_sites = Array.isArray(obj.sites) && obj.sites.length > 0;
6
+ // lattice may be an object or (in some raw formats) a 3x3 array, so only reject nullish
7
+ const has_lattice = obj.lattice !== undefined && obj.lattice !== null && typeof obj.lattice === `object`;
9
8
  return has_sites && has_lattice;
10
9
  }