matterviz 0.4.0 → 0.4.2

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 (527) hide show
  1. package/dist/EmptyState.svelte +10 -4
  2. package/dist/FilePicker.svelte +12 -14
  3. package/dist/Icon.svelte +7 -4
  4. package/dist/MillerIndexInput.svelte +2 -2
  5. package/dist/app.css +53 -0
  6. package/dist/brillouin/BrillouinZone.svelte +132 -219
  7. package/dist/brillouin/BrillouinZone.svelte.d.ts +9 -20
  8. package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
  9. package/dist/brillouin/BrillouinZoneExportPane.svelte +47 -96
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  11. package/dist/brillouin/BrillouinZoneInfoPane.svelte +15 -42
  12. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
  13. package/dist/brillouin/BrillouinZoneScene.svelte +63 -230
  14. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +3 -23
  15. package/dist/brillouin/ReciprocalVectors.svelte +39 -0
  16. package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
  17. package/dist/brillouin/compute.d.ts +2 -0
  18. package/dist/brillouin/compute.js +80 -77
  19. package/dist/brillouin/geometry.d.ts +8 -0
  20. package/dist/brillouin/geometry.js +57 -0
  21. package/dist/brillouin/index.d.ts +2 -0
  22. package/dist/brillouin/index.js +2 -0
  23. package/dist/brillouin/types.d.ts +2 -2
  24. package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
  25. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
  26. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +143 -246
  27. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
  28. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +652 -976
  29. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
  30. package/dist/chempot-diagram/async-compute.svelte.js +1 -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 +3 -3
  34. package/dist/chempot-diagram/compute.js +3 -1
  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.d.ts +0 -4
  45. package/dist/colors/index.js +21 -22
  46. package/dist/composition/BarChart.svelte +37 -31
  47. package/dist/composition/BubbleChart.svelte +17 -17
  48. package/dist/composition/Composition.svelte +7 -11
  49. package/dist/composition/Formula.svelte +18 -25
  50. package/dist/composition/FormulaFilter.svelte +96 -98
  51. package/dist/composition/PieChart.svelte +60 -46
  52. package/dist/composition/chem-sys.js +3 -2
  53. package/dist/composition/format.js +4 -3
  54. package/dist/composition/index.d.ts +2 -0
  55. package/dist/composition/index.js +14 -0
  56. package/dist/composition/parse.d.ts +2 -3
  57. package/dist/composition/parse.js +27 -28
  58. package/dist/constants.js +11 -9
  59. package/dist/controls.d.ts +1 -0
  60. package/dist/controls.js +0 -1
  61. package/dist/convex-hull/ConvexHull.svelte +20 -25
  62. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
  63. package/dist/convex-hull/ConvexHull2D.svelte +176 -256
  64. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  65. package/dist/convex-hull/ConvexHull3D.svelte +269 -804
  66. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  67. package/dist/convex-hull/ConvexHull4D.svelte +236 -755
  68. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  69. package/dist/convex-hull/ConvexHullChrome.svelte +264 -0
  70. package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
  71. package/dist/convex-hull/ConvexHullControls.svelte +128 -49
  72. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
  73. package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
  74. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
  75. package/dist/convex-hull/ConvexHullStats.svelte +210 -351
  76. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
  77. package/dist/convex-hull/ConvexHullTooltip.svelte +16 -14
  78. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
  79. package/dist/convex-hull/GasPressureControls.svelte +5 -12
  80. package/dist/convex-hull/StructurePopup.svelte +17 -21
  81. package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
  82. package/dist/convex-hull/TemperatureSlider.svelte +4 -10
  83. package/dist/convex-hull/barycentric-coords.d.ts +2 -4
  84. package/dist/convex-hull/barycentric-coords.js +6 -33
  85. package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
  86. package/dist/convex-hull/canvas-interactions.svelte.js +279 -0
  87. package/dist/convex-hull/helpers.d.ts +47 -17
  88. package/dist/convex-hull/helpers.js +186 -101
  89. package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
  90. package/dist/convex-hull/hull-state.svelte.js +124 -0
  91. package/dist/convex-hull/index.d.ts +9 -7
  92. package/dist/convex-hull/index.js +7 -2
  93. package/dist/convex-hull/thermodynamics.js +109 -937
  94. package/dist/convex-hull/types.d.ts +12 -4
  95. package/dist/convex-hull/types.js +12 -0
  96. package/dist/coordination/CoordinationBarPlot.svelte +41 -43
  97. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  98. package/dist/coordination/calc-coordination.d.ts +1 -1
  99. package/dist/coordination/calc-coordination.js +28 -25
  100. package/dist/element/BohrAtom.svelte +6 -8
  101. package/dist/element/ElementHeading.svelte +4 -1
  102. package/dist/element/ElementPhoto.svelte +11 -9
  103. package/dist/element/ElementStats.svelte +12 -10
  104. package/dist/element/ElementTile.svelte +24 -29
  105. package/dist/element/ElementTile.svelte.d.ts +1 -1
  106. package/dist/element/Nucleus.svelte +4 -2
  107. package/dist/element/data.d.ts +1 -2
  108. package/dist/element/helpers.d.ts +4 -0
  109. package/dist/element/helpers.js +18 -0
  110. package/dist/element/index.d.ts +1 -0
  111. package/dist/element/index.js +3 -0
  112. package/dist/feedback/DragOverlay.svelte +5 -3
  113. package/dist/feedback/DragOverlay.svelte.d.ts +2 -1
  114. package/dist/feedback/StatusMessage.svelte +20 -7
  115. package/dist/fermi-surface/FermiSlice.svelte +21 -18
  116. package/dist/fermi-surface/FermiSurface.svelte +78 -165
  117. package/dist/fermi-surface/FermiSurface.svelte.d.ts +9 -20
  118. package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
  119. package/dist/fermi-surface/FermiSurfaceScene.svelte +93 -272
  120. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
  121. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
  122. package/dist/fermi-surface/compute.js +14 -13
  123. package/dist/fermi-surface/export.js +4 -15
  124. package/dist/fermi-surface/index.d.ts +0 -1
  125. package/dist/fermi-surface/index.js +0 -1
  126. package/dist/fermi-surface/parse.d.ts +1 -1
  127. package/dist/fermi-surface/parse.js +84 -97
  128. package/dist/fermi-surface/types.d.ts +2 -2
  129. package/dist/heatmap-matrix/HeatmapMatrix.svelte +161 -185
  130. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +6 -5
  131. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +12 -9
  132. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
  133. package/dist/heatmap-matrix/index.d.ts +8 -2
  134. package/dist/icons.d.ts +4 -0
  135. package/dist/icons.js +4 -0
  136. package/dist/index.d.ts +1 -0
  137. package/dist/index.js +1 -0
  138. package/dist/io/ExportPane.svelte +170 -0
  139. package/dist/io/ExportPane.svelte.d.ts +17 -0
  140. package/dist/io/decompress.d.ts +2 -1
  141. package/dist/io/decompress.js +22 -36
  142. package/dist/io/export.d.ts +9 -1
  143. package/dist/io/export.js +37 -29
  144. package/dist/io/fetch.d.ts +2 -4
  145. package/dist/io/fetch.js +0 -11
  146. package/dist/io/file-drop.d.ts +7 -0
  147. package/dist/io/file-drop.js +13 -0
  148. package/dist/io/index.d.ts +1 -0
  149. package/dist/io/index.js +3 -0
  150. package/dist/io/is-binary.d.ts +9 -0
  151. package/dist/io/is-binary.js +45 -1
  152. package/dist/io/types.d.ts +13 -0
  153. package/dist/io/url-drop.js +13 -25
  154. package/dist/isosurface/Isosurface.svelte +17 -23
  155. package/dist/isosurface/IsosurfaceControls.svelte +37 -42
  156. package/dist/isosurface/parse-vaspwave.d.ts +3 -0
  157. package/dist/isosurface/parse-vaspwave.js +138 -0
  158. package/dist/isosurface/parse.js +50 -48
  159. package/dist/labels.d.ts +6 -2
  160. package/dist/labels.js +44 -14
  161. package/dist/layout/FullscreenButton.svelte +34 -0
  162. package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
  163. package/dist/layout/FullscreenToggle.svelte +12 -12
  164. package/dist/layout/InfoCard.svelte +7 -18
  165. package/dist/layout/InfoTag.svelte +1 -3
  166. package/dist/layout/NumberRangeInput.svelte +46 -0
  167. package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
  168. package/dist/layout/PropertyFilter.svelte +2 -6
  169. package/dist/layout/SettingsSection.svelte +21 -17
  170. package/dist/layout/SubpageGrid.svelte +3 -1
  171. package/dist/layout/ViewerChrome.svelte +115 -0
  172. package/dist/layout/ViewerChrome.svelte.d.ts +18 -0
  173. package/dist/layout/fullscreen.d.ts +4 -0
  174. package/dist/layout/fullscreen.js +3 -5
  175. package/dist/layout/fullscreen.svelte.d.ts +8 -0
  176. package/dist/layout/fullscreen.svelte.js +36 -0
  177. package/dist/layout/index.d.ts +4 -0
  178. package/dist/layout/index.js +4 -0
  179. package/dist/layout/json-tree/JsonNode.svelte +8 -11
  180. package/dist/layout/json-tree/JsonTree.svelte +53 -77
  181. package/dist/layout/json-tree/JsonValue.svelte +7 -15
  182. package/dist/layout/json-tree/utils.js +14 -23
  183. package/dist/math.d.ts +9 -3
  184. package/dist/math.js +37 -21
  185. package/dist/overlays/ContextMenu.svelte +4 -2
  186. package/dist/overlays/CopyButton.svelte +11 -5
  187. package/dist/overlays/DragControlTab.svelte +6 -1
  188. package/dist/overlays/DraggablePane.svelte +81 -26
  189. package/dist/overlays/DraggablePane.svelte.d.ts +1 -0
  190. package/dist/overlays/GlassChip.svelte +30 -0
  191. package/dist/overlays/GlassChip.svelte.d.ts +8 -0
  192. package/dist/overlays/InfoPaneCards.svelte +11 -23
  193. package/dist/overlays/index.d.ts +11 -0
  194. package/dist/overlays/index.js +26 -0
  195. package/dist/overlays/portal.d.ts +2 -0
  196. package/dist/overlays/portal.js +14 -0
  197. package/dist/periodic-table/PeriodicTable.svelte +115 -146
  198. package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
  199. package/dist/periodic-table/PeriodicTableControls.svelte +11 -63
  200. package/dist/periodic-table/TableInset.svelte +9 -4
  201. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +50 -71
  202. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
  203. package/dist/phase-diagram/PhaseDiagramControls.svelte +73 -96
  204. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
  205. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +4 -2
  206. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
  207. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +49 -134
  208. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
  209. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
  210. package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
  211. package/dist/phase-diagram/build-diagram.js +3 -3
  212. package/dist/phase-diagram/colors.js +1 -1
  213. package/dist/phase-diagram/diagram-input.d.ts +1 -2
  214. package/dist/phase-diagram/parse.d.ts +2 -1
  215. package/dist/phase-diagram/parse.js +15 -15
  216. package/dist/phase-diagram/svg-to-diagram.js +21 -15
  217. package/dist/phase-diagram/utils.js +2 -3
  218. package/dist/plot/bar/BarPlot.svelte +494 -692
  219. package/dist/plot/bar/BarPlot.svelte.d.ts +9 -15
  220. package/dist/plot/bar/BarPlotControls.svelte +1 -3
  221. package/dist/plot/bar/BarPlotControls.svelte.d.ts +5 -7
  222. package/dist/plot/bar/SpacegroupBarPlot.svelte +31 -37
  223. package/dist/plot/bar/data.d.ts +5 -4
  224. package/dist/plot/bar/data.js +2 -1
  225. package/dist/plot/box/BoxPlot.svelte +361 -439
  226. package/dist/plot/box/BoxPlot.svelte.d.ts +6 -3
  227. package/dist/plot/box/BoxPlotControls.svelte.d.ts +1 -1
  228. package/dist/plot/box/Violin.svelte.d.ts +2 -1
  229. package/dist/plot/box/box-plot.d.ts +3 -2
  230. package/dist/plot/box/box-plot.js +6 -3
  231. package/dist/plot/box/kde.d.ts +2 -1
  232. package/dist/plot/box/kde.js +4 -4
  233. package/dist/plot/core/auto-place.d.ts +1 -1
  234. package/dist/plot/core/auto-place.js +5 -2
  235. package/dist/plot/core/axis-utils.d.ts +12 -7
  236. package/dist/plot/core/axis-utils.js +48 -48
  237. package/dist/plot/core/components/AxisLabel.svelte +82 -20
  238. package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
  239. package/dist/plot/core/components/ColorBar.svelte +106 -111
  240. package/dist/plot/core/components/ColorBar.svelte.d.ts +5 -4
  241. package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
  242. package/dist/plot/core/components/FillArea.svelte +10 -17
  243. package/dist/plot/core/components/HierarchyControls.svelte +249 -0
  244. package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
  245. package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
  246. package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
  247. package/dist/plot/core/components/Line.svelte +21 -11
  248. package/dist/plot/core/components/Line.svelte.d.ts +5 -2
  249. package/dist/plot/core/components/PlotAxis.svelte +42 -18
  250. package/dist/plot/core/components/PlotAxis.svelte.d.ts +2 -1
  251. package/dist/plot/core/components/PlotControls.svelte +65 -41
  252. package/dist/plot/core/components/PlotControls.svelte.d.ts +1 -1
  253. package/dist/plot/core/components/PlotLegend.svelte +31 -35
  254. package/dist/plot/core/components/PlotMarginals.svelte +616 -0
  255. package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
  256. package/dist/plot/core/components/PlotTooltip.svelte +1 -1
  257. package/dist/plot/core/components/PortalSelect.svelte +4 -8
  258. package/dist/plot/core/components/ReferenceLine.svelte +27 -24
  259. package/dist/plot/core/components/ReferenceLine3D.svelte +56 -59
  260. package/dist/plot/core/components/ReferenceLine3D.svelte.d.ts +4 -4
  261. package/dist/plot/core/components/ReferencePlane.svelte +9 -10
  262. package/dist/plot/core/components/ReferencePlane.svelte.d.ts +4 -4
  263. package/dist/plot/core/components/ZeroLines.svelte +4 -8
  264. package/dist/plot/core/components/ZoomRect.svelte +1 -2
  265. package/dist/plot/core/components/index.d.ts +1 -0
  266. package/dist/plot/core/components/index.js +1 -0
  267. package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
  268. package/dist/plot/core/data-cleaning-signal.js +467 -0
  269. package/dist/plot/core/data-cleaning.d.ts +2 -42
  270. package/dist/plot/core/data-cleaning.js +29 -476
  271. package/dist/plot/core/data-transform.js +9 -5
  272. package/dist/plot/core/fill-utils.d.ts +7 -4
  273. package/dist/plot/core/fill-utils.js +34 -9
  274. package/dist/plot/core/index.d.ts +1 -0
  275. package/dist/plot/core/index.js +1 -0
  276. package/dist/plot/core/interactions.d.ts +5 -1
  277. package/dist/plot/core/interactions.js +14 -2
  278. package/dist/plot/core/layout.d.ts +3 -1
  279. package/dist/plot/core/layout.js +22 -13
  280. package/dist/plot/core/marginals.d.ts +170 -0
  281. package/dist/plot/core/marginals.js +436 -0
  282. package/dist/plot/core/pan-zoom.svelte.d.ts +35 -0
  283. package/dist/plot/core/pan-zoom.svelte.js +221 -0
  284. package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
  285. package/dist/plot/core/placed-tween.svelte.js +68 -0
  286. package/dist/plot/core/reference-line.d.ts +10 -10
  287. package/dist/plot/core/reference-line.js +7 -7
  288. package/dist/plot/core/scales.d.ts +40 -25
  289. package/dist/plot/core/scales.js +49 -21
  290. package/dist/plot/core/svg.d.ts +2 -1
  291. package/dist/plot/core/types/fills.d.ts +101 -0
  292. package/dist/plot/core/types/fills.js +15 -0
  293. package/dist/plot/core/types/plot-3d.d.ts +87 -0
  294. package/dist/plot/core/types/plot-3d.js +4 -0
  295. package/dist/plot/core/types/reference-lines.d.ts +140 -0
  296. package/dist/plot/core/types/reference-lines.js +9 -0
  297. package/dist/plot/core/types.d.ts +47 -331
  298. package/dist/plot/core/types.js +23 -20
  299. package/dist/plot/core/utils/hierarchy-chart.d.ts +51 -0
  300. package/dist/plot/core/utils/hierarchy-chart.js +179 -0
  301. package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
  302. package/dist/plot/core/utils/hierarchy-labels.js +99 -0
  303. package/dist/plot/core/utils/label-placement.d.ts +1 -1
  304. package/dist/plot/core/utils/label-placement.js +5 -5
  305. package/dist/plot/core/utils.d.ts +2 -1
  306. package/dist/plot/histogram/Histogram.svelte +373 -631
  307. package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
  308. package/dist/plot/histogram/HistogramControls.svelte +30 -28
  309. package/dist/plot/histogram/HistogramControls.svelte.d.ts +1 -1
  310. package/dist/plot/histogram/histogram.d.ts +31 -0
  311. package/dist/plot/histogram/histogram.js +70 -0
  312. package/dist/plot/histogram/index.d.ts +1 -0
  313. package/dist/plot/histogram/index.js +1 -0
  314. package/dist/plot/index.d.ts +1 -0
  315. package/dist/plot/index.js +1 -0
  316. package/dist/plot/sankey/Sankey.svelte +79 -73
  317. package/dist/plot/sankey/Sankey.svelte.d.ts +3 -3
  318. package/dist/plot/sankey/SankeyControls.svelte +22 -16
  319. package/dist/plot/sankey/sankey.js +3 -1
  320. package/dist/plot/scatter/BinnedScatterPlot.svelte +264 -112
  321. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +11 -4
  322. package/dist/plot/scatter/ElementScatter.svelte +4 -1
  323. package/dist/plot/scatter/ScatterPlot.svelte +623 -821
  324. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +9 -15
  325. package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
  326. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
  327. package/dist/plot/scatter/ScatterPoint.svelte +16 -9
  328. package/dist/plot/scatter/binned-scatter-types.d.ts +6 -12
  329. package/dist/plot/scatter/binned-scatter-types.js +6 -1
  330. package/dist/plot/scatter/index.d.ts +1 -1
  331. package/dist/plot/scatter/scatter-data.d.ts +1 -1
  332. package/dist/plot/scatter/scatter-data.js +8 -7
  333. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +40 -60
  334. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +6 -14
  335. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +17 -15
  336. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte.d.ts +5 -5
  337. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +232 -234
  338. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +5 -14
  339. package/dist/plot/scatter-3d/Surface3D.svelte +9 -17
  340. package/dist/plot/scatter-3d/Surface3D.svelte.d.ts +4 -3
  341. package/dist/plot/sunburst/Sunburst.svelte +256 -338
  342. package/dist/plot/sunburst/Sunburst.svelte.d.ts +4 -3
  343. package/dist/plot/sunburst/index.d.ts +1 -1
  344. package/dist/plot/sunburst/index.js +2 -1
  345. package/dist/plot/sunburst/render.d.ts +2 -2
  346. package/dist/plot/sunburst/render.js +47 -22
  347. package/dist/plot/sunburst/sunburst.d.ts +5 -1
  348. package/dist/plot/sunburst/sunburst.js +14 -4
  349. package/dist/plot/treemap/Treemap.svelte +907 -0
  350. package/dist/plot/treemap/Treemap.svelte.d.ts +84 -0
  351. package/dist/plot/treemap/index.d.ts +3 -0
  352. package/dist/plot/treemap/index.js +4 -0
  353. package/dist/plot/treemap/treemap.d.ts +26 -0
  354. package/dist/plot/treemap/treemap.js +99 -0
  355. package/dist/rdf/RdfPlot.svelte +22 -26
  356. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  357. package/dist/rdf/calc-rdf.js +4 -8
  358. package/dist/sanitize.js +14 -3
  359. package/dist/scene/SceneCamera.svelte +62 -0
  360. package/dist/scene/SceneCamera.svelte.d.ts +19 -0
  361. package/dist/scene/bind-renderer.svelte.d.ts +2 -0
  362. package/dist/scene/bind-renderer.svelte.js +22 -0
  363. package/dist/scene/index.d.ts +4 -0
  364. package/dist/scene/index.js +5 -0
  365. package/dist/scene/props.js +52 -0
  366. package/dist/scene/types.d.ts +26 -0
  367. package/dist/scene/types.js +1 -0
  368. package/dist/settings.d.ts +33 -11
  369. package/dist/settings.js +136 -51
  370. package/dist/spectral/Bands.svelte +231 -237
  371. package/dist/spectral/Bands.svelte.d.ts +3 -2
  372. package/dist/spectral/BandsAndDos.svelte +29 -29
  373. package/dist/spectral/BrillouinBandsDos.svelte +21 -29
  374. package/dist/spectral/Dos.svelte +75 -77
  375. package/dist/spectral/Dos.svelte.d.ts +2 -1
  376. package/dist/spectral/helpers.d.ts +9 -9
  377. package/dist/spectral/helpers.js +66 -70
  378. package/dist/state.svelte.d.ts +0 -7
  379. package/dist/state.svelte.js +5 -24
  380. package/dist/structure/Arrow.svelte +6 -21
  381. package/dist/structure/ArrowInstances.svelte +160 -0
  382. package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
  383. package/dist/structure/AtomLegend.svelte +115 -75
  384. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  385. package/dist/structure/Bond.svelte +31 -23
  386. package/dist/structure/CanvasTooltip.svelte +16 -3
  387. package/dist/structure/CellSelect.svelte +22 -29
  388. package/dist/structure/CellSelect.svelte.d.ts +2 -1
  389. package/dist/structure/Cylinder.svelte +24 -40
  390. package/dist/structure/InstancedAtoms.svelte +114 -0
  391. package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
  392. package/dist/structure/Lattice.svelte +85 -149
  393. package/dist/structure/SiteLabels.svelte +122 -0
  394. package/dist/structure/SiteLabels.svelte.d.ts +18 -0
  395. package/dist/structure/Structure.svelte +725 -735
  396. package/dist/structure/Structure.svelte.d.ts +8 -16
  397. package/dist/structure/StructureCarousel.svelte +630 -0
  398. package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
  399. package/dist/structure/StructureControls.svelte +298 -325
  400. package/dist/structure/StructureControls.svelte.d.ts +5 -3
  401. package/dist/structure/StructureExportPane.svelte +62 -168
  402. package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
  403. package/dist/structure/StructureInfoPane.svelte +77 -69
  404. package/dist/structure/StructureInfoPane.svelte.d.ts +6 -6
  405. package/dist/structure/StructureScene.svelte +758 -600
  406. package/dist/structure/StructureScene.svelte.d.ts +24 -20
  407. package/dist/structure/StructureViewport.svelte +386 -0
  408. package/dist/structure/StructureViewport.svelte.d.ts +63 -0
  409. package/dist/structure/atom-label-placement.d.ts +18 -0
  410. package/dist/structure/atom-label-placement.js +115 -0
  411. package/dist/structure/atom-properties.d.ts +3 -1
  412. package/dist/structure/atom-properties.js +115 -54
  413. package/dist/structure/bond-order-perception.js +2 -4
  414. package/dist/structure/bonding.d.ts +12 -2
  415. package/dist/structure/bonding.js +172 -73
  416. package/dist/structure/edit-history.d.ts +6 -0
  417. package/dist/structure/edit-history.js +27 -0
  418. package/dist/structure/export.d.ts +25 -4
  419. package/dist/structure/export.js +103 -153
  420. package/dist/structure/format-detect.d.ts +1 -0
  421. package/dist/structure/format-detect.js +22 -0
  422. package/dist/structure/geometry.d.ts +9 -0
  423. package/dist/structure/geometry.js +27 -0
  424. package/dist/structure/index.d.ts +18 -1
  425. package/dist/structure/index.js +15 -2
  426. package/dist/structure/measure.d.ts +1 -1
  427. package/dist/structure/measure.js +6 -12
  428. package/dist/structure/parse.d.ts +5 -3
  429. package/dist/structure/parse.js +551 -567
  430. package/dist/structure/partial-occupancy.d.ts +0 -1
  431. package/dist/structure/partial-occupancy.js +5 -3
  432. package/dist/structure/pbc.d.ts +1 -1
  433. package/dist/structure/pbc.js +204 -51
  434. package/dist/structure/polyhedra.d.ts +40 -0
  435. package/dist/structure/polyhedra.js +587 -0
  436. package/dist/structure/site.d.ts +4 -0
  437. package/dist/structure/site.js +1 -0
  438. package/dist/structure/supercell.d.ts +1 -2
  439. package/dist/structure/supercell.js +10 -15
  440. package/dist/structure/validation.js +5 -6
  441. package/dist/symmetry/SymmetryElementControls.svelte +69 -0
  442. package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
  443. package/dist/symmetry/SymmetryElements.svelte +350 -0
  444. package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
  445. package/dist/symmetry/SymmetryStats.svelte +142 -49
  446. package/dist/symmetry/WyckoffTable.svelte +58 -16
  447. package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
  448. package/dist/symmetry/cell-transform.js +8 -14
  449. package/dist/symmetry/index.d.ts +15 -4
  450. package/dist/symmetry/index.js +308 -81
  451. package/dist/symmetry/spacegroups.d.ts +5 -1
  452. package/dist/symmetry/spacegroups.js +18 -3
  453. package/dist/symmetry/symmetry-elements.d.ts +33 -0
  454. package/dist/symmetry/symmetry-elements.js +521 -0
  455. package/dist/symmetry/wyckoff-db.d.ts +9 -0
  456. package/dist/symmetry/wyckoff-db.js +87 -0
  457. package/dist/table/HeatmapTable.svelte +1104 -378
  458. package/dist/table/HeatmapTable.svelte.d.ts +12 -2
  459. package/dist/table/ToggleMenu.svelte +5 -12
  460. package/dist/table/index.d.ts +21 -6
  461. package/dist/table/index.js +34 -21
  462. package/dist/theme/ThemeControl.svelte +16 -8
  463. package/dist/theme/index.d.ts +1 -5
  464. package/dist/theme/index.js +4 -10
  465. package/dist/theme/themes.mjs +14 -7
  466. package/dist/tooltip/KCoords.svelte +4 -1
  467. package/dist/tooltip/TooltipContent.svelte +2 -5
  468. package/dist/trajectory/Trajectory.svelte +556 -352
  469. package/dist/trajectory/Trajectory.svelte.d.ts +10 -22
  470. package/dist/trajectory/TrajectoryError.svelte +11 -8
  471. package/dist/trajectory/TrajectoryExportPane.svelte +28 -54
  472. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
  473. package/dist/trajectory/TrajectoryInfoPane.svelte +88 -99
  474. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
  475. package/dist/trajectory/constants.js +6 -2
  476. package/dist/trajectory/extract.js +73 -71
  477. package/dist/trajectory/format-detect.d.ts +0 -1
  478. package/dist/trajectory/format-detect.js +13 -17
  479. package/dist/trajectory/frame-reader.d.ts +2 -1
  480. package/dist/trajectory/frame-reader.js +74 -136
  481. package/dist/trajectory/helpers.d.ts +12 -2
  482. package/dist/trajectory/helpers.js +68 -37
  483. package/dist/trajectory/index.d.ts +1 -0
  484. package/dist/trajectory/index.js +3 -0
  485. package/dist/trajectory/parse/ase.d.ts +9 -1
  486. package/dist/trajectory/parse/ase.js +47 -32
  487. package/dist/trajectory/parse/diagnostics.d.ts +3 -0
  488. package/dist/trajectory/parse/diagnostics.js +14 -0
  489. package/dist/trajectory/parse/h5-utils.d.ts +13 -0
  490. package/dist/trajectory/parse/h5-utils.js +109 -0
  491. package/dist/trajectory/parse/hdf5.d.ts +1 -1
  492. package/dist/trajectory/parse/hdf5.js +116 -106
  493. package/dist/trajectory/parse/index.d.ts +3 -4
  494. package/dist/trajectory/parse/index.js +68 -119
  495. package/dist/trajectory/parse/lammps.d.ts +0 -2
  496. package/dist/trajectory/parse/lammps.js +14 -16
  497. package/dist/trajectory/parse/pymatgen.d.ts +2 -0
  498. package/dist/trajectory/parse/pymatgen.js +74 -0
  499. package/dist/trajectory/parse/vasp.js +13 -9
  500. package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
  501. package/dist/trajectory/parse/vaspout-electronic.js +207 -0
  502. package/dist/trajectory/parse/vaspout-h5.d.ts +5 -0
  503. package/dist/trajectory/parse/vaspout-h5.js +284 -0
  504. package/dist/trajectory/parse/xyz.d.ts +9 -21
  505. package/dist/trajectory/parse/xyz.js +38 -39
  506. package/dist/trajectory/plotting.d.ts +8 -10
  507. package/dist/trajectory/plotting.js +102 -127
  508. package/dist/utils.d.ts +4 -0
  509. package/dist/utils.js +8 -1
  510. package/dist/xrd/XrdPlot.svelte +56 -85
  511. package/dist/xrd/broadening.d.ts +2 -1
  512. package/dist/xrd/broadening.js +2 -1
  513. package/dist/xrd/calc-xrd.js +8 -15
  514. package/dist/xrd/index.d.ts +2 -2
  515. package/dist/xrd/parse.d.ts +0 -1
  516. package/dist/xrd/parse.js +56 -73
  517. package/package.json +77 -36
  518. package/dist/api/mp.d.ts +0 -6
  519. package/dist/api/mp.js +0 -22
  520. package/dist/element/data.json +0 -11864
  521. package/dist/fermi-surface/marching-cubes.d.ts +0 -2
  522. package/dist/fermi-surface/marching-cubes.js +0 -2
  523. package/dist/plot/core/hover-lock.svelte.d.ts +0 -14
  524. package/dist/plot/core/hover-lock.svelte.js +0 -45
  525. package/dist/plot/sunburst/SunburstControls.svelte +0 -200
  526. package/dist/structure/label-placement.d.ts +0 -14
  527. package/dist/structure/label-placement.js +0 -72
@@ -0,0 +1,587 @@
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, has_framework_potential, is_spectator_center, } 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
+ // A bonded neighbor counts as a polyhedron vertex only if it's an anion-former:
298
+ // a nonmetal or metalloid that is more electronegative than the center. This keeps
299
+ // spurious cation-cation bonds (e.g. Ti-Ba in perovskites, Li-P in thiophosphates)
300
+ // from contaminating coordination environments.
301
+ function is_anion_vertex(center_en, center_is_metal, neighbor_element, electronegativity_margin) {
302
+ if (!neighbor_element)
303
+ return false;
304
+ const n_data = element_lookup.get(neighbor_element);
305
+ if (n_data?.metal)
306
+ return false;
307
+ const n_en = n_data?.electronegativity ?? null;
308
+ if (center_en !== null && n_en !== null) {
309
+ return n_en > center_en + electronegativity_margin;
310
+ }
311
+ // EN data missing: only metal centers with nonmetal neighbors qualify
312
+ return center_is_metal && n_data?.nonmetal === true;
313
+ }
314
+ // --- Top-level polyhedra computation ---
315
+ // Detect coordination polyhedra from the rendered bond graph, VESTA-style:
316
+ // vertices are anion-former neighbors (nonmetals/metalloids more electronegative
317
+ // than the center) within `1 + distance_factor` of the shortest such bond, so
318
+ // over-long bond-graph noise doesn't inflate e.g. PO4 tetrahedra. Spectator A-site
319
+ // cations (alkali, heavy alkaline-earth) are skipped when framework cations exist,
320
+ // CN > max_neighbors hulls (e.g. CN-12 cuboctahedra) are skipped, and
321
+ // boundary-truncated copies only render when their vertex count matches the max
322
+ // among all copies of the same original site. Every polyhedron corner is a
323
+ // displayed atom (boundary shells are completed upstream by bond-completing image
324
+ // atoms - see find_image_atoms in pbc.ts).
325
+ export function compute_polyhedra(structure, bonds, options = {}) {
326
+ const {
327
+ // Neighbor-count fallbacks derive from DEFAULTS.structure so they can't drift
328
+ // from the polyhedra_min/max_neighbors settings defaults
329
+ 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;
330
+ const sites = structure?.sites;
331
+ if (!sites?.length || bonds.length === 0)
332
+ return [];
333
+ const adjacency = build_adjacency(bonds);
334
+ const excluded = new Set(excluded_center_elements);
335
+ const included = new Set(included_center_elements);
336
+ const site_elements = sites.map((site) => get_majority_element(site));
337
+ const unique_elements = [
338
+ ...new Set(site_elements.filter((el) => el !== null)),
339
+ ];
340
+ const center_info_cache = new Map();
341
+ const center_info = (element) => {
342
+ let info = center_info_cache.get(element);
343
+ if (!info) {
344
+ const data = element_lookup.get(element);
345
+ const center_en = data?.electronegativity ?? null;
346
+ const r_center = data?.covalent_radius ?? null;
347
+ const accepts = new Set(unique_elements.filter((n_elem) => is_anion_vertex(center_en, data?.metal === true, n_elem, electronegativity_margin)));
348
+ const radii_sums = new Map(unique_elements.map((n_elem) => {
349
+ const r_n = element_lookup.get(n_elem)?.covalent_radius ?? null;
350
+ return [n_elem, r_center !== null && r_n !== null ? r_center + r_n : null];
351
+ }));
352
+ info = { accepts, radii_sums };
353
+ center_info_cache.set(element, info);
354
+ }
355
+ return info;
356
+ };
357
+ const candidates = [];
358
+ for (const [site_idx, neighbors] of adjacency) {
359
+ if (neighbors.size < min_neighbors)
360
+ continue;
361
+ const element = site_elements[site_idx];
362
+ if (!element || excluded.has(element))
363
+ continue;
364
+ const { accepts, radii_sums } = center_info(element);
365
+ if (accepts.size === 0)
366
+ continue;
367
+ const [cx, cy, cz] = sites[site_idx].xyz;
368
+ // Bonded anion vertices (parallel arrays to avoid per-vertex object churn)
369
+ const vert_idxs = [];
370
+ const vert_dists = [];
371
+ let min_dist = Infinity;
372
+ for (const idx of neighbors) {
373
+ const n_elem = site_elements[idx];
374
+ if (!n_elem || !accepts.has(n_elem))
375
+ continue;
376
+ const [nx, ny, nz] = sites[idx].xyz;
377
+ const dist = Math.hypot(nx - cx, ny - cy, nz - cz);
378
+ vert_idxs.push(idx);
379
+ vert_dists.push(dist);
380
+ if (dist < min_dist)
381
+ min_dist = dist;
382
+ }
383
+ if (vert_idxs.length < min_neighbors)
384
+ continue;
385
+ // Trim over-long bonds relative to the shortest anion bond (VESTA-like local
386
+ // cutoff): keeps distorted/Jahn-Teller octahedra intact but rejects e.g. a 5th
387
+ // oxygen at 2.5 Å around P whose true tetrahedron has 1.5 Å bonds
388
+ const cutoff = min_dist * (1 + distance_factor);
389
+ const vertex_site_idxs = [];
390
+ let [norm_sum, norm_count] = [0, 0];
391
+ for (let pos = 0; pos < vert_idxs.length; pos++) {
392
+ if (vert_dists[pos] > cutoff)
393
+ continue;
394
+ const idx = vert_idxs[pos];
395
+ vertex_site_idxs.push(idx);
396
+ // Bond softness: how stretched the kept bonds are vs the covalent-radii sum
397
+ const n_elem = site_elements[idx];
398
+ const r_sum = n_elem ? (radii_sums.get(n_elem) ?? null) : null;
399
+ if (r_sum !== null) {
400
+ norm_sum += vert_dists[pos] / r_sum;
401
+ norm_count++;
402
+ }
403
+ }
404
+ if (vertex_site_idxs.length < min_neighbors)
405
+ continue;
406
+ candidates.push({
407
+ site_idx,
408
+ orig_idx: get_orig_site_idx(sites[site_idx], site_idx),
409
+ element,
410
+ vertex_site_idxs,
411
+ mean_norm_dist: norm_count > 0 ? norm_sum / norm_count : null,
412
+ });
413
+ }
414
+ // Pass 2: hide spectator A-site cations when the composition contains a
415
+ // potential framework cation (a non-spectator element less electronegative than
416
+ // the structure's most electronegative element, i.e. one that could coordinate
417
+ // the anions). Composition-based rather than candidate-based so boundary
418
+ // truncation of framework polyhedra doesn't promote Li/Na/Ba clutter; purely
419
+ // ionic binaries like NaCl or CaF2 still draw their spectator polyhedra.
420
+ const has_framework = has_framework_potential(unique_elements);
421
+ // Weakly-bound center species (mean bond length well beyond the covalent-radii
422
+ // sum, e.g. lone-pair Bi3+ with 8 long Bi-O bonds) are hidden when a
423
+ // strongly-bound framework species exists - mirrors how pyrochlore-type figures
424
+ // show only the B-site octahedra
425
+ const norm_by_species = new Map();
426
+ for (const { element, mean_norm_dist } of candidates) {
427
+ if (mean_norm_dist === null)
428
+ continue;
429
+ const entry = norm_by_species.get(element) ?? { sum: 0, count: 0 };
430
+ entry.sum += mean_norm_dist;
431
+ entry.count++;
432
+ norm_by_species.set(element, entry);
433
+ }
434
+ const species_norm = (el) => {
435
+ const entry = norm_by_species.get(el);
436
+ return entry ? entry.sum / entry.count : null;
437
+ };
438
+ const has_strong_species = [...norm_by_species.keys()].some((el) => (species_norm(el) ?? Infinity) <= weak_bond_norm && !is_spectator_center(el));
439
+ const is_weak_species = (el) => has_strong_species && (species_norm(el) ?? 0) > weak_bond_norm;
440
+ const visible = candidates.filter(({ element }) => {
441
+ if (included.has(element))
442
+ return true;
443
+ if (is_spectator_center(element) && has_framework)
444
+ return false;
445
+ return !is_weak_species(element);
446
+ });
447
+ // Pass 3: boundary completeness - copies of the same original site only render
448
+ // at the max observed vertex count, so any remaining truncated copies (bond
449
+ // completing image atoms handle most) are skipped
450
+ const max_cn_by_orig = new Map();
451
+ for (const { orig_idx, vertex_site_idxs } of visible) {
452
+ if (vertex_site_idxs.length > (max_cn_by_orig.get(orig_idx) ?? 0)) {
453
+ max_cn_by_orig.set(orig_idx, vertex_site_idxs.length);
454
+ }
455
+ }
456
+ // Pass 4: CN cap (after completeness so capped interior copies don't let
457
+ // truncated boundary copies of the same site slip through; force-included
458
+ // elements bypass the cap - an explicit user request beats the clutter
459
+ // heuristic), then build hulls, deduping identical center positions (base
460
+ // atom vs PBC image)
461
+ const polyhedra = [];
462
+ const seen_positions = new Set();
463
+ for (const { site_idx, orig_idx, element, vertex_site_idxs } of visible) {
464
+ if (vertex_site_idxs.length !== max_cn_by_orig.get(orig_idx))
465
+ continue;
466
+ if (vertex_site_idxs.length > max_neighbors && !included.has(element))
467
+ continue;
468
+ const [px, py, pz] = sites[site_idx].xyz;
469
+ const pos_key = `${Math.round(px * 1e3)},${Math.round(py * 1e3)},${Math.round(pz * 1e3)}`;
470
+ if (seen_positions.has(pos_key))
471
+ continue;
472
+ seen_positions.add(pos_key);
473
+ const hull = convex_hull_3d(vertex_site_idxs.map((idx) => sites[idx].xyz));
474
+ if (hull.faces.length === 0 || hull.volume < volume_eps)
475
+ continue;
476
+ polyhedra.push({
477
+ center_site_idx: site_idx,
478
+ center_orig_idx: orig_idx,
479
+ center_element: element,
480
+ vertices: hull.vertices,
481
+ vertex_site_idxs: hull.input_idxs.map((input_idx) => vertex_site_idxs[input_idx]),
482
+ faces: hull.faces,
483
+ volume: hull.volume,
484
+ });
485
+ }
486
+ return polyhedra;
487
+ }
488
+ // --- Merged render buffers ---
489
+ // Merge all polyhedra into single non-indexed position/color arrays (one draw call)
490
+ // plus crease-edge segments for outlines. Edges interior to coplanar face groups
491
+ // (e.g. quad diagonals on a cube) are omitted. `get_vertex_color` resolves the
492
+ // color of each hull vertex (e.g. the vertex atom's element color, the center
493
+ // atom's color, or a uniform custom color) - parsed colors are cached by string.
494
+ export function merge_polyhedra_buffers(polyhedra, get_vertex_color, coplanar_tol = 1e-3) {
495
+ let triangle_count = 0;
496
+ for (const poly of polyhedra)
497
+ triangle_count += poly.faces.length;
498
+ const positions = new Float32Array(triangle_count * 9);
499
+ const colors = new Float32Array(triangle_count * 9);
500
+ // A closed triangulated surface has at most 3F/2 unique edges
501
+ const edge_positions = new Float32Array(Math.ceil(triangle_count * 1.5) * 6);
502
+ const rgb_cache = new Map();
503
+ let offset = 0;
504
+ let edge_offset = 0;
505
+ // Per-polyhedron scratch: crease detection tracks the first face normal seen
506
+ // per undirected edge (packed vert_a * 2^16 + vert_b key)
507
+ const edge_normals = new Map();
508
+ for (const poly of polyhedra) {
509
+ const verts = poly.vertices;
510
+ // Resolve per-hull-vertex colors once
511
+ const vert_rgb = new Float32Array(verts.length * 3);
512
+ for (let v_idx = 0; v_idx < verts.length; v_idx++) {
513
+ const color = get_vertex_color(poly, v_idx);
514
+ let channels = rgb_cache.get(color);
515
+ if (!channels) {
516
+ // d3-color handles hex, rgb()/rgba() (d3 property-color scales) and named colors
517
+ const { r, g, b } = parse_rgb(color);
518
+ channels = Number.isFinite(r) ? [r / 255, g / 255, b / 255] : [0.5, 0.5, 0.5];
519
+ rgb_cache.set(color, channels);
520
+ }
521
+ vert_rgb[v_idx * 3] = channels[0];
522
+ vert_rgb[v_idx * 3 + 1] = channels[1];
523
+ vert_rgb[v_idx * 3 + 2] = channels[2];
524
+ }
525
+ edge_normals.clear();
526
+ for (const [idx_a, idx_b, idx_c] of poly.faces) {
527
+ const [ax, ay, az] = verts[idx_a];
528
+ const [bx, by, bz] = verts[idx_b];
529
+ const [px, py, pz] = verts[idx_c];
530
+ // Scalar face normal for crease detection
531
+ let nx = (by - ay) * (pz - az) - (bz - az) * (py - ay);
532
+ let ny = (bz - az) * (px - ax) - (bx - ax) * (pz - az);
533
+ let nz = (bx - ax) * (py - ay) - (by - ay) * (px - ax);
534
+ const len = Math.hypot(nx, ny, nz);
535
+ if (len > 0) {
536
+ nx /= len;
537
+ ny /= len;
538
+ nz /= len;
539
+ }
540
+ for (const v_idx of [idx_a, idx_b, idx_c]) {
541
+ const vert = verts[v_idx];
542
+ positions[offset] = vert[0];
543
+ positions[offset + 1] = vert[1];
544
+ positions[offset + 2] = vert[2];
545
+ colors[offset] = vert_rgb[v_idx * 3];
546
+ colors[offset + 1] = vert_rgb[v_idx * 3 + 1];
547
+ colors[offset + 2] = vert_rgb[v_idx * 3 + 2];
548
+ offset += 3;
549
+ }
550
+ for (const [from, to] of [
551
+ [idx_a, idx_b],
552
+ [idx_b, idx_c],
553
+ [idx_c, idx_a],
554
+ ]) {
555
+ const key = from < to ? from * 65536 + to : to * 65536 + from;
556
+ const entry = edge_normals.get(key);
557
+ if (entry) {
558
+ entry.shared = true;
559
+ entry.crease = nx * entry.nx + ny * entry.ny + nz * entry.nz < 1 - coplanar_tol;
560
+ }
561
+ else
562
+ edge_normals.set(key, { nx, ny, nz, crease: false, shared: false });
563
+ }
564
+ }
565
+ // Draw an edge unless both adjacent faces are coplanar (quad diagonal)
566
+ for (const [key, entry] of edge_normals) {
567
+ if (entry.shared && !entry.crease)
568
+ continue;
569
+ const from = verts[Math.floor(key / 65536)];
570
+ const to = verts[key % 65536];
571
+ edge_positions[edge_offset] = from[0];
572
+ edge_positions[edge_offset + 1] = from[1];
573
+ edge_positions[edge_offset + 2] = from[2];
574
+ edge_positions[edge_offset + 3] = to[0];
575
+ edge_positions[edge_offset + 4] = to[1];
576
+ edge_positions[edge_offset + 5] = to[2];
577
+ edge_offset += 6;
578
+ }
579
+ }
580
+ return {
581
+ positions,
582
+ colors,
583
+ edge_positions: edge_positions.slice(0, edge_offset),
584
+ triangle_count,
585
+ edge_count: edge_offset / 6,
586
+ };
587
+ }
@@ -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 });
@@ -1,8 +1,7 @@
1
1
  import type { Vec3 } from '../math';
2
- import { scale_lattice_matrix } from '../math';
3
2
  import type { Crystal } from './index';
4
3
  export declare function parse_supercell_scaling(scaling: string | number | Vec3): Vec3;
5
4
  export declare function generate_lattice_points(scaling_factors: Vec3): Vec3[];
6
- export { scale_lattice_matrix };
5
+ export { scale_lattice_matrix } from '../math';
7
6
  export declare function make_supercell(structure: Crystal, scaling: string | number | Vec3, to_unit_cell?: boolean): Crystal;
8
7
  export declare function is_valid_supercell_input(input: string): boolean;
@@ -1,5 +1,4 @@
1
1
  import * as math from '../math';
2
- import { scale_lattice_matrix } from '../math';
3
2
  import { wrap_frac_coord } from './pbc';
4
3
  import { normalize_structure_bond } from './bonding';
5
4
  const mod = (value, divisor) => ((value % divisor) + divisor) % divisor;
@@ -79,7 +78,7 @@ export function generate_lattice_points(scaling_factors) {
79
78
  return points;
80
79
  }
81
80
  // Re-export from $lib/math for backward compatibility
82
- export { scale_lattice_matrix };
81
+ export { scale_lattice_matrix } from '../math';
83
82
  // Create a supercell from a Crystal
84
83
  // Takes original structure, scaling factors, and whether to fold coordinates back to unit cell (default: true)
85
84
  // Returns new supercell structure
@@ -96,26 +95,22 @@ export function make_supercell(structure, scaling, to_unit_cell = true) {
96
95
  }
97
96
  const orig_matrix = structure.lattice.matrix;
98
97
  // Create new scaled lattice
99
- const new_lattice_matrix = scale_lattice_matrix(orig_matrix, supercell_scaling);
100
- const lattice_params = math.calc_lattice_params(new_lattice_matrix);
101
- const new_lattice = {
102
- ...structure.lattice,
103
- matrix: new_lattice_matrix,
104
- ...lattice_params,
105
- };
98
+ const new_matrix = math.scale_lattice_matrix(orig_matrix, supercell_scaling);
99
+ const lattice_params = math.calc_lattice_params(new_matrix);
100
+ const new_lattice = { ...structure.lattice, matrix: new_matrix, ...lattice_params };
106
101
  // Pre-allocate sites array
107
102
  const n_sites = structure.sites.length;
108
103
  const new_sites = Array(n_sites * total_cells);
109
104
  // Destructure lattice vectors for fast inline arithmetic (avoid function calls in hot loop)
110
105
  const [[ax, ay, az], [bx, by, bz], [cx, cy, cz]] = orig_matrix;
111
- const [sx, sy, sz] = supercell_scaling;
112
106
  let write_idx = 0;
113
107
  const sites = structure.sites;
114
108
  // Loop order: k, j, i to match typical pymatgen/standard ordering
115
109
  for (let kk = 0; kk < scale_z; kk++) {
116
110
  for (let jj = 0; jj < scale_y; jj++) {
117
111
  for (let ii = 0; ii < scale_x; ii++) {
118
- const label_suffix = total_cells > 1 ? `_${ii}${jj}${kk}` : ``;
112
+ // 1x1x1 short-circuits above, so every site gets a cell-index suffix
113
+ const label_suffix = `_${ii}${jj}${kk}`;
119
114
  // Translation = ii * vec_a + jj * vec_b + kk * vec_c (inlined for performance)
120
115
  const tx = ii * ax + jj * bx + kk * cx;
121
116
  const ty = ii * ay + jj * by + kk * cy;
@@ -123,9 +118,9 @@ export function make_supercell(structure, scaling, to_unit_cell = true) {
123
118
  for (let site_idx = 0; site_idx < n_sites; site_idx++) {
124
119
  const site = sites[site_idx];
125
120
  // new_abc = (old_abc + [ii, jj, kk]) / supercell_scaling
126
- let new_a = (site.abc[0] + ii) / sx;
127
- let new_b = (site.abc[1] + jj) / sy;
128
- let new_c = (site.abc[2] + kk) / sz;
121
+ let new_a = (site.abc[0] + ii) / scale_x;
122
+ let new_b = (site.abc[1] + jj) / scale_y;
123
+ let new_c = (site.abc[2] + kk) / scale_z;
129
124
  if (to_unit_cell) {
130
125
  new_a = wrap_frac_coord(new_a);
131
126
  new_b = wrap_frac_coord(new_b);
@@ -135,7 +130,7 @@ export function make_supercell(structure, scaling, to_unit_cell = true) {
135
130
  species: site.species,
136
131
  xyz: [site.xyz[0] + tx, site.xyz[1] + ty, site.xyz[2] + tz],
137
132
  abc: [new_a, new_b, new_c],
138
- label: label_suffix ? `${site.label}${label_suffix}` : site.label,
133
+ label: `${site.label}${label_suffix}`,
139
134
  properties: { ...site.properties, orig_unit_cell_idx: site_idx },
140
135
  };
141
136
  }