matterviz 0.4.0 → 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.
- package/dist/brillouin/BrillouinZone.svelte +68 -145
- package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -14
- package/dist/brillouin/BrillouinZoneExportPane.svelte +43 -96
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +9 -32
- package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
- package/dist/brillouin/BrillouinZoneScene.svelte +49 -203
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +3 -23
- package/dist/brillouin/ReciprocalVectors.svelte +39 -0
- package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
- package/dist/brillouin/compute.d.ts +2 -0
- package/dist/brillouin/compute.js +80 -77
- package/dist/brillouin/geometry.d.ts +8 -0
- package/dist/brillouin/geometry.js +57 -0
- package/dist/brillouin/index.d.ts +2 -0
- package/dist/brillouin/index.js +2 -0
- package/dist/brillouin/types.d.ts +2 -2
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +100 -191
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +176 -464
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
- package/dist/chempot-diagram/color.d.ts +3 -6
- package/dist/chempot-diagram/color.js +5 -5
- package/dist/chempot-diagram/compute.d.ts +3 -3
- package/dist/chempot-diagram/compute.js +3 -1
- package/dist/chempot-diagram/controls-state.svelte.d.ts +10 -0
- package/dist/chempot-diagram/controls-state.svelte.js +42 -0
- package/dist/chempot-diagram/export.d.ts +47 -0
- package/dist/chempot-diagram/export.js +133 -0
- package/dist/chempot-diagram/index.d.ts +1 -0
- package/dist/chempot-diagram/index.js +1 -0
- package/dist/chempot-diagram/pointer.d.ts +0 -10
- package/dist/chempot-diagram/pointer.js +4 -4
- package/dist/chempot-diagram/types.d.ts +3 -3
- package/dist/colors/index.js +2 -2
- package/dist/composition/FormulaFilter.svelte +6 -5
- package/dist/composition/PieChart.svelte +5 -5
- package/dist/composition/chem-sys.js +3 -2
- package/dist/composition/format.js +3 -2
- package/dist/composition/parse.d.ts +0 -1
- package/dist/composition/parse.js +17 -19
- package/dist/controls.d.ts +1 -0
- package/dist/controls.js +0 -1
- package/dist/convex-hull/ConvexHull.svelte +8 -10
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
- package/dist/convex-hull/ConvexHull2D.svelte +94 -175
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +176 -680
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +180 -680
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullChrome.svelte +268 -0
- package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
- package/dist/convex-hull/ConvexHullControls.svelte +88 -7
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
- package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
- package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
- package/dist/convex-hull/ConvexHullStats.svelte +29 -168
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +11 -2
- package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
- package/dist/convex-hull/barycentric-coords.d.ts +2 -4
- package/dist/convex-hull/barycentric-coords.js +6 -33
- package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
- package/dist/convex-hull/canvas-interactions.svelte.js +278 -0
- package/dist/convex-hull/helpers.d.ts +39 -7
- package/dist/convex-hull/helpers.js +154 -69
- package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
- package/dist/convex-hull/hull-state.svelte.js +124 -0
- package/dist/convex-hull/index.d.ts +9 -7
- package/dist/convex-hull/index.js +7 -2
- package/dist/convex-hull/thermodynamics.js +91 -920
- package/dist/convex-hull/types.d.ts +12 -4
- package/dist/convex-hull/types.js +12 -0
- package/dist/coordination/CoordinationBarPlot.svelte +4 -11
- package/dist/element/BohrAtom.svelte +2 -1
- package/dist/element/ElementTile.svelte.d.ts +1 -1
- package/dist/element/index.d.ts +4 -0
- package/dist/element/index.js +18 -0
- package/dist/feedback/DragOverlay.svelte +3 -1
- package/dist/feedback/DragOverlay.svelte.d.ts +1 -0
- package/dist/feedback/StatusMessage.svelte +13 -3
- package/dist/fermi-surface/FermiSurface.svelte +67 -146
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -14
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +72 -224
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
- package/dist/fermi-surface/compute.js +11 -10
- package/dist/fermi-surface/export.js +4 -15
- package/dist/fermi-surface/index.d.ts +0 -1
- package/dist/fermi-surface/index.js +0 -1
- package/dist/fermi-surface/parse.d.ts +1 -1
- package/dist/fermi-surface/parse.js +64 -75
- package/dist/fermi-surface/types.d.ts +2 -2
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +55 -40
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +4 -3
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +3 -2
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
- package/dist/heatmap-matrix/index.d.ts +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/io/ExportPane.svelte +166 -0
- package/dist/io/ExportPane.svelte.d.ts +17 -0
- package/dist/io/decompress.js +1 -2
- package/dist/io/export.d.ts +5 -1
- package/dist/io/export.js +32 -28
- package/dist/io/fetch.d.ts +2 -1
- package/dist/io/file-drop.d.ts +7 -0
- package/dist/io/file-drop.js +13 -0
- package/dist/io/index.d.ts +2 -0
- package/dist/io/index.js +10 -0
- package/dist/io/types.d.ts +13 -0
- package/dist/isosurface/parse.js +46 -44
- package/dist/labels.js +1 -1
- package/dist/layout/FullscreenButton.svelte +33 -0
- package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
- package/dist/layout/FullscreenToggle.svelte +8 -14
- package/dist/layout/ViewerChrome.svelte +116 -0
- package/dist/layout/ViewerChrome.svelte.d.ts +17 -0
- package/dist/layout/fullscreen.d.ts +4 -0
- package/dist/layout/fullscreen.svelte.d.ts +8 -0
- package/dist/layout/fullscreen.svelte.js +37 -0
- package/dist/layout/index.d.ts +3 -0
- package/dist/layout/index.js +3 -0
- package/dist/math.d.ts +7 -3
- package/dist/math.js +18 -21
- package/dist/overlays/index.d.ts +4 -0
- package/dist/periodic-table/PeriodicTable.svelte +9 -8
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramControls.svelte +3 -2
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +47 -132
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
- package/dist/phase-diagram/colors.js +1 -1
- package/dist/phase-diagram/parse.d.ts +2 -1
- package/dist/plot/bar/BarPlot.svelte +79 -316
- package/dist/plot/bar/BarPlot.svelte.d.ts +7 -15
- package/dist/plot/bar/BarPlotControls.svelte.d.ts +1 -1
- package/dist/plot/bar/SpacegroupBarPlot.svelte +2 -1
- package/dist/plot/box/BoxPlot.svelte +76 -246
- package/dist/plot/box/BoxPlot.svelte.d.ts +4 -3
- package/dist/plot/box/BoxPlotControls.svelte.d.ts +1 -1
- package/dist/plot/box/Violin.svelte.d.ts +1 -1
- package/dist/plot/box/box-plot.d.ts +3 -2
- package/dist/plot/box/box-plot.js +5 -2
- package/dist/plot/box/kde.d.ts +2 -1
- package/dist/plot/box/kde.js +4 -4
- package/dist/plot/core/auto-place.d.ts +1 -1
- package/dist/plot/core/auto-place.js +4 -1
- package/dist/plot/core/components/ColorBar.svelte +5 -5
- package/dist/plot/core/components/ColorBar.svelte.d.ts +5 -4
- package/dist/plot/core/components/Line.svelte +3 -2
- package/dist/plot/core/components/Line.svelte.d.ts +3 -2
- package/dist/plot/core/components/PlotAxis.svelte +2 -1
- package/dist/plot/core/components/PlotAxis.svelte.d.ts +2 -1
- package/dist/plot/core/components/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/core/components/ReferenceLine3D.svelte +2 -2
- package/dist/plot/core/components/ReferenceLine3D.svelte.d.ts +4 -4
- package/dist/plot/core/components/ReferencePlane.svelte +2 -2
- package/dist/plot/core/components/ReferencePlane.svelte.d.ts +4 -4
- package/dist/plot/core/data-cleaning.js +18 -18
- package/dist/plot/core/fill-utils.d.ts +4 -3
- package/dist/plot/core/fill-utils.js +6 -3
- package/dist/plot/core/interactions.d.ts +5 -1
- package/dist/plot/core/interactions.js +14 -0
- package/dist/plot/core/pan-zoom.svelte.d.ts +35 -0
- package/dist/plot/core/pan-zoom.svelte.js +221 -0
- package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
- package/dist/plot/core/placed-tween.svelte.js +68 -0
- package/dist/plot/core/reference-line.d.ts +10 -10
- package/dist/plot/core/reference-line.js +6 -6
- package/dist/plot/core/scales.d.ts +17 -25
- package/dist/plot/core/scales.js +10 -8
- package/dist/plot/core/svg.d.ts +2 -1
- package/dist/plot/core/types.d.ts +18 -7
- package/dist/plot/core/utils/label-placement.d.ts +1 -1
- package/dist/plot/core/utils/label-placement.js +3 -3
- package/dist/plot/core/utils.d.ts +2 -1
- package/dist/plot/histogram/Histogram.svelte +77 -314
- package/dist/plot/histogram/HistogramControls.svelte.d.ts +1 -1
- package/dist/plot/sankey/Sankey.svelte +2 -5
- package/dist/plot/sankey/Sankey.svelte.d.ts +1 -1
- package/dist/plot/sankey/sankey.js +3 -1
- package/dist/plot/scatter/BinnedScatterPlot.svelte +3 -5
- package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +4 -4
- package/dist/plot/scatter/ScatterPlot.svelte +160 -450
- package/dist/plot/scatter/ScatterPlot.svelte.d.ts +7 -15
- package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/scatter/binned-scatter-types.d.ts +4 -11
- package/dist/plot/scatter/index.d.ts +1 -1
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte +15 -26
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +6 -14
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +9 -10
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte.d.ts +5 -5
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +122 -121
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +5 -14
- package/dist/plot/scatter-3d/Surface3D.svelte +6 -5
- package/dist/plot/scatter-3d/Surface3D.svelte.d.ts +4 -3
- package/dist/plot/sunburst/Sunburst.svelte +16 -20
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +4 -3
- package/dist/plot/sunburst/SunburstControls.svelte.d.ts +1 -1
- package/dist/plot/sunburst/sunburst.js +4 -1
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/sanitize.js +13 -2
- package/dist/scene/SceneCamera.svelte +62 -0
- package/dist/scene/SceneCamera.svelte.d.ts +19 -0
- package/dist/scene/bind-renderer.svelte.d.ts +2 -0
- package/dist/scene/bind-renderer.svelte.js +14 -0
- package/dist/scene/index.d.ts +4 -0
- package/dist/scene/index.js +5 -0
- package/dist/scene/props.js +52 -0
- package/dist/scene/types.d.ts +26 -0
- package/dist/scene/types.js +1 -0
- package/dist/settings.d.ts +14 -2
- package/dist/settings.js +59 -1
- package/dist/spectral/Bands.svelte +8 -7
- package/dist/spectral/Bands.svelte.d.ts +3 -2
- package/dist/spectral/BandsAndDos.svelte +22 -24
- package/dist/spectral/BrillouinBandsDos.svelte +3 -3
- package/dist/spectral/Dos.svelte +5 -4
- package/dist/spectral/Dos.svelte.d.ts +2 -1
- package/dist/spectral/helpers.d.ts +6 -6
- package/dist/spectral/helpers.js +43 -37
- package/dist/state.svelte.d.ts +0 -7
- package/dist/state.svelte.js +0 -6
- package/dist/structure/Arrow.svelte +2 -4
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/CanvasTooltip.svelte +1 -0
- package/dist/structure/CellSelect.svelte +11 -3
- package/dist/structure/CellSelect.svelte.d.ts +2 -1
- package/dist/structure/Lattice.svelte +2 -2
- package/dist/structure/Structure.svelte +291 -355
- package/dist/structure/Structure.svelte.d.ts +5 -15
- package/dist/structure/StructureControls.svelte +217 -2
- package/dist/structure/StructureControls.svelte.d.ts +5 -3
- package/dist/structure/StructureExportPane.svelte +54 -156
- package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
- package/dist/structure/StructureInfoPane.svelte +5 -3
- package/dist/structure/StructureInfoPane.svelte.d.ts +5 -5
- package/dist/structure/StructureScene.svelte +365 -198
- package/dist/structure/StructureScene.svelte.d.ts +22 -20
- package/dist/structure/{label-placement.d.ts → atom-label-placement.d.ts} +3 -3
- package/dist/structure/{label-placement.js → atom-label-placement.js} +12 -2
- package/dist/structure/atom-properties.d.ts +1 -1
- package/dist/structure/atom-properties.js +11 -16
- package/dist/structure/bond-order-perception.js +2 -4
- package/dist/structure/bonding.d.ts +3 -0
- package/dist/structure/bonding.js +91 -48
- package/dist/structure/export.d.ts +24 -4
- package/dist/structure/export.js +64 -122
- package/dist/structure/index.d.ts +2 -0
- package/dist/structure/index.js +2 -0
- package/dist/structure/parse.d.ts +3 -2
- package/dist/structure/parse.js +333 -370
- package/dist/structure/partial-occupancy.d.ts +0 -1
- package/dist/structure/partial-occupancy.js +1 -1
- package/dist/structure/pbc.d.ts +1 -1
- package/dist/structure/pbc.js +186 -13
- package/dist/structure/polyhedra.d.ts +41 -0
- package/dist/structure/polyhedra.js +602 -0
- package/dist/structure/site.d.ts +4 -0
- package/dist/structure/site.js +1 -0
- package/dist/structure/supercell.js +3 -2
- package/dist/structure/validation.js +5 -6
- package/dist/symmetry/SymmetryElementControls.svelte +69 -0
- package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
- package/dist/symmetry/SymmetryElements.svelte +354 -0
- package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
- package/dist/symmetry/SymmetryStats.svelte +111 -6
- package/dist/symmetry/WyckoffTable.svelte +68 -7
- package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
- package/dist/symmetry/cell-transform.js +7 -14
- package/dist/symmetry/index.d.ts +14 -4
- package/dist/symmetry/index.js +301 -80
- package/dist/symmetry/spacegroups.d.ts +5 -1
- package/dist/symmetry/spacegroups.js +15 -1
- package/dist/symmetry/symmetry-elements.d.ts +33 -0
- package/dist/symmetry/symmetry-elements.js +521 -0
- package/dist/symmetry/wyckoff-db.d.ts +9 -0
- package/dist/symmetry/wyckoff-db.js +87 -0
- package/dist/table/HeatmapTable.svelte +4 -15
- package/dist/table/HeatmapTable.svelte.d.ts +1 -1
- package/dist/trajectory/Trajectory.svelte +58 -61
- package/dist/trajectory/Trajectory.svelte.d.ts +10 -22
- package/dist/trajectory/TrajectoryExportPane.svelte +15 -24
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
- package/dist/trajectory/TrajectoryInfoPane.svelte +3 -2
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
- package/dist/trajectory/constants.js +6 -2
- package/dist/trajectory/extract.js +17 -37
- package/dist/trajectory/format-detect.d.ts +0 -1
- package/dist/trajectory/format-detect.js +3 -9
- package/dist/trajectory/frame-reader.d.ts +0 -1
- package/dist/trajectory/frame-reader.js +62 -128
- package/dist/trajectory/helpers.d.ts +10 -2
- package/dist/trajectory/helpers.js +56 -36
- package/dist/trajectory/parse/ase.d.ts +9 -1
- package/dist/trajectory/parse/ase.js +47 -32
- package/dist/trajectory/parse/diagnostics.d.ts +3 -0
- package/dist/trajectory/parse/diagnostics.js +14 -0
- package/dist/trajectory/parse/index.d.ts +1 -1
- package/dist/trajectory/parse/index.js +54 -102
- package/dist/trajectory/parse/lammps.d.ts +0 -2
- package/dist/trajectory/parse/lammps.js +8 -6
- package/dist/trajectory/parse/pymatgen.d.ts +2 -0
- package/dist/trajectory/parse/pymatgen.js +74 -0
- package/dist/trajectory/parse/vasp.js +4 -3
- package/dist/trajectory/parse/xyz.d.ts +9 -21
- package/dist/trajectory/parse/xyz.js +28 -33
- package/dist/trajectory/plotting.d.ts +0 -1
- package/dist/trajectory/plotting.js +3 -100
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +1 -1
- package/dist/xrd/XrdPlot.svelte +14 -29
- package/dist/xrd/broadening.d.ts +2 -1
- package/dist/xrd/calc-xrd.js +6 -11
- package/dist/xrd/index.d.ts +2 -2
- package/package.json +29 -16
- package/dist/element/data.json +0 -11864
- package/dist/fermi-surface/marching-cubes.d.ts +0 -2
- package/dist/fermi-surface/marching-cubes.js +0 -2
- package/dist/plot/core/hover-lock.svelte.d.ts +0 -14
- package/dist/plot/core/hover-lock.svelte.js +0 -45
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { D3InterpolateName } from '../colors'
|
|
3
|
-
import {
|
|
3
|
+
import { get_d3_interpolator } from '../colors'
|
|
4
4
|
import type { ElementSymbol } from '../element'
|
|
5
5
|
import { element_data } from '../element'
|
|
6
6
|
import Isosurface from '../isosurface/Isosurface.svelte'
|
|
@@ -9,12 +9,9 @@
|
|
|
9
9
|
import { format_num } from '../labels'
|
|
10
10
|
import type { Vec3 } from '../math'
|
|
11
11
|
import * as math from '../math'
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
VectorColorMode,
|
|
16
|
-
VectorLayerConfig,
|
|
17
|
-
} from '../settings'
|
|
12
|
+
import { bind_renderer, build_orbit_props, SceneCamera } from '../scene'
|
|
13
|
+
import type { SceneControlProps } from '../scene'
|
|
14
|
+
import type { ShowBonds, VectorColorMode, VectorLayerConfig } from '../settings'
|
|
18
15
|
import { DEFAULTS } from '../settings'
|
|
19
16
|
import { create_pulse_animation } from '../effects.svelte'
|
|
20
17
|
import { colors } from '../state.svelte'
|
|
@@ -42,6 +39,9 @@
|
|
|
42
39
|
get_orig_site_idx,
|
|
43
40
|
get_property_colors,
|
|
44
41
|
} from './atom-properties'
|
|
42
|
+
import type { SymmetryElement } from '../symmetry'
|
|
43
|
+
import { has_visible_symmetry_overlay } from '../symmetry/symmetry-elements'
|
|
44
|
+
import SymmetryElements from '../symmetry/SymmetryElements.svelte'
|
|
45
45
|
import * as measure from './measure'
|
|
46
46
|
import {
|
|
47
47
|
compute_slice_geometry,
|
|
@@ -49,11 +49,12 @@
|
|
|
49
49
|
PARTIAL_OCCUPANCY_CAP_ARC,
|
|
50
50
|
} from './partial-occupancy'
|
|
51
51
|
import type { MoyoDataset } from '@spglib/moyo-wasm'
|
|
52
|
-
import { T
|
|
52
|
+
import { T } from '@threlte/core'
|
|
53
53
|
import * as extras from '@threlte/extras'
|
|
54
54
|
import { type ComponentProps, type Snippet, untrack } from 'svelte'
|
|
55
55
|
import { SvelteMap, SvelteSet } from 'svelte/reactivity'
|
|
56
|
-
import {
|
|
56
|
+
import { BufferAttribute, BufferGeometry, Color, DoubleSide, Vector3 } from 'three'
|
|
57
|
+
import type { Mesh, Object3D } from 'three'
|
|
57
58
|
import Bond from './Bond.svelte'
|
|
58
59
|
import type { BondEditResult, BondingStrategy, BondKeyTarget } from './bonding'
|
|
59
60
|
import {
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
get_bond_key,
|
|
66
67
|
get_bond_render_matrices,
|
|
67
68
|
get_explicit_bond_metadata,
|
|
69
|
+
get_majority_element,
|
|
68
70
|
set_bond_order as apply_set_bond_order,
|
|
69
71
|
structure_bond_to_bond_pair,
|
|
70
72
|
} from './bonding'
|
|
@@ -77,7 +79,9 @@
|
|
|
77
79
|
choose_site_label_offset,
|
|
78
80
|
LABEL_OFFSET_EPS,
|
|
79
81
|
make_label_position_calculator,
|
|
80
|
-
} from './label-placement'
|
|
82
|
+
} from './atom-label-placement'
|
|
83
|
+
import type { PolyhedraColorMode, Polyhedron } from './polyhedra'
|
|
84
|
+
import { compute_polyhedra, merge_polyhedra_buffers } from './polyhedra'
|
|
81
85
|
|
|
82
86
|
type InstancedAtomGroup = {
|
|
83
87
|
element: string
|
|
@@ -168,12 +172,27 @@
|
|
|
168
172
|
auto_bond_order = DEFAULTS.structure.auto_bond_order,
|
|
169
173
|
aromatic_display = DEFAULTS.structure.aromatic_display,
|
|
170
174
|
bonding_options = {},
|
|
175
|
+
show_polyhedra = DEFAULTS.structure.show_polyhedra,
|
|
176
|
+
polyhedra_opacity = DEFAULTS.structure.polyhedra_opacity,
|
|
177
|
+
polyhedra_show_edges = DEFAULTS.structure.polyhedra_show_edges,
|
|
178
|
+
polyhedra_edge_color = DEFAULTS.structure.polyhedra_edge_color,
|
|
179
|
+
polyhedra_color_mode = DEFAULTS.structure.polyhedra_color_mode,
|
|
180
|
+
polyhedra_color = DEFAULTS.structure.polyhedra_color,
|
|
181
|
+
polyhedra_hide_center_atoms = DEFAULTS.structure.polyhedra_hide_center_atoms,
|
|
182
|
+
polyhedra_min_neighbors = DEFAULTS.structure.polyhedra_min_neighbors,
|
|
183
|
+
polyhedra_max_neighbors = DEFAULTS.structure.polyhedra_max_neighbors,
|
|
184
|
+
polyhedra_excluded_elements = DEFAULTS.structure.polyhedra_excluded_elements,
|
|
185
|
+
polyhedra_included_elements = DEFAULTS.structure.polyhedra_included_elements,
|
|
186
|
+
polyhedra_rendered_elements = $bindable<string[]>([]),
|
|
171
187
|
fov = DEFAULTS.structure.fov,
|
|
172
188
|
initial_zoom = DEFAULTS.structure.initial_zoom,
|
|
173
189
|
ambient_light = DEFAULTS.structure.ambient_light,
|
|
174
190
|
directional_light = DEFAULTS.structure.directional_light,
|
|
175
191
|
sphere_segments = DEFAULTS.structure.sphere_segments,
|
|
176
192
|
lattice_props = {},
|
|
193
|
+
symmetry_elements = [],
|
|
194
|
+
symmetry_elements_props = {},
|
|
195
|
+
symmetry_declutter = true,
|
|
177
196
|
atom_label,
|
|
178
197
|
camera_is_moving = $bindable(false),
|
|
179
198
|
width = 0,
|
|
@@ -218,7 +237,7 @@
|
|
|
218
237
|
dragging_atoms = $bindable(false),
|
|
219
238
|
volumetric_data = undefined,
|
|
220
239
|
isosurface_settings = DEFAULT_ISOSURFACE_SETTINGS,
|
|
221
|
-
}: {
|
|
240
|
+
}: SceneControlProps & {
|
|
222
241
|
structure?: AnyStructure
|
|
223
242
|
base_structure?: AnyStructure // The original structure without image atoms, used for property color calculation
|
|
224
243
|
atom_radius?: number // scale factor for atomic radii
|
|
@@ -226,15 +245,6 @@
|
|
|
226
245
|
// determined by the atomic radius of the element
|
|
227
246
|
camera_position?: [x: number, y: number, z: number] // initial camera position from which to render the scene
|
|
228
247
|
camera_target?: Vec3 // external orbit-controls target for pan synchronization
|
|
229
|
-
camera_projection?: CameraProjection // camera projection type
|
|
230
|
-
rotation_damping?: number // rotation damping factor (how quickly the rotation comes to rest after mouse release)
|
|
231
|
-
// zoom level of the camera
|
|
232
|
-
max_zoom?: number
|
|
233
|
-
min_zoom?: number
|
|
234
|
-
rotate_speed?: number // rotation speed. set to 0 to disable rotation.
|
|
235
|
-
zoom_speed?: number // zoom speed. set to 0 to disable zooming.
|
|
236
|
-
pan_speed?: number // pan speed. set to 0 to disable panning.
|
|
237
|
-
zoom_to_cursor?: boolean // zoom toward cursor position instead of scene center
|
|
238
248
|
show_atoms?: boolean
|
|
239
249
|
show_bonds?: ShowBonds
|
|
240
250
|
show_site_labels?: boolean
|
|
@@ -250,30 +260,46 @@
|
|
|
250
260
|
vector_shaft_radius?: number
|
|
251
261
|
vector_arrow_head_radius?: number
|
|
252
262
|
vector_arrow_head_length?: number
|
|
253
|
-
gizmo?: boolean | ComponentProps<typeof extras.Gizmo>
|
|
254
263
|
hovered_idx?: number | null
|
|
255
264
|
hovered_site?: Site | null
|
|
256
265
|
float_fmt?: string
|
|
257
|
-
auto_rotate?: number
|
|
258
|
-
initial_zoom?: number
|
|
259
266
|
bond_thickness?: number
|
|
260
267
|
bond_color?: string
|
|
261
268
|
bonding_strategy?: BondingStrategy
|
|
262
269
|
auto_bond_order?: boolean
|
|
263
270
|
aromatic_display?: `aromatic` | `kekule`
|
|
264
271
|
bonding_options?: Record<string, unknown>
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
272
|
+
show_polyhedra?: ShowBonds // when to render coordination polyhedra
|
|
273
|
+
polyhedra_opacity?: number
|
|
274
|
+
polyhedra_show_edges?: boolean
|
|
275
|
+
polyhedra_edge_color?: string
|
|
276
|
+
polyhedra_color_mode?: PolyhedraColorMode
|
|
277
|
+
polyhedra_color?: string // custom color used when polyhedra_color_mode is 'uniform'
|
|
278
|
+
polyhedra_hide_center_atoms?: boolean
|
|
279
|
+
polyhedra_min_neighbors?: number // min coordination number to form a polyhedron
|
|
280
|
+
polyhedra_max_neighbors?: number // max CN - skips e.g. CN-12 cuboctahedra
|
|
281
|
+
polyhedra_excluded_elements?: readonly string[] // elements never used as polyhedra centers
|
|
282
|
+
polyhedra_included_elements?: readonly string[] // force-include (bypasses spectator hiding)
|
|
283
|
+
polyhedra_rendered_elements?: string[] // (output) elements that currently have polyhedra
|
|
268
284
|
sphere_segments?: number
|
|
269
285
|
lattice_props?: ComponentProps<typeof Lattice>
|
|
286
|
+
// Symmetry elements (from symmetry_elements_from_ops) to overlay on the structure.
|
|
287
|
+
// Fractional coords must refer to the SAME cell as the rendered lattice (moyo
|
|
288
|
+
// operations are in the input-cell frame, i.e. the original untransformed cell).
|
|
289
|
+
symmetry_elements?: SymmetryElement[]
|
|
290
|
+
symmetry_elements_props?: Omit<ComponentProps<typeof SymmetryElements>, `elements` | `lattice`>
|
|
291
|
+
// Auto-reduce visual clutter while a symmetry-element overlay is visible: hides
|
|
292
|
+
// coordination polyhedra and calculated bonds, and shrinks atoms so axes/planes/
|
|
293
|
+
// centers stay readable. Purely derived — toggling the overlay off restores the
|
|
294
|
+
// configured appearance.
|
|
295
|
+
symmetry_declutter?: boolean
|
|
270
296
|
atom_label?: Snippet<[{ site: Site; site_idx: number }]>
|
|
271
297
|
site_label_size?: number
|
|
272
298
|
site_label_offset?: Vec3
|
|
273
299
|
site_label_bg_color?: string
|
|
274
300
|
site_label_color?: string
|
|
275
301
|
site_label_padding?: number
|
|
276
|
-
camera_is_moving?: boolean //
|
|
302
|
+
camera_is_moving?: boolean // bindable: true while orbit controls are active
|
|
277
303
|
width?: number // Viewer dimensions for responsive zoom
|
|
278
304
|
height?: number
|
|
279
305
|
// measurement props
|
|
@@ -291,9 +317,6 @@
|
|
|
291
317
|
active_sites?: number[]
|
|
292
318
|
active_highlight_color?: string
|
|
293
319
|
rotation?: Vec3 // rotation control prop
|
|
294
|
-
// Expose scene and camera for external use (e.g. export pane)
|
|
295
|
-
scene?: Scene
|
|
296
|
-
camera?: Camera
|
|
297
320
|
orbit_controls?: ComponentProps<typeof extras.OrbitControls>[`ref`] // OrbitControls instance
|
|
298
321
|
rotation_target_ref?: Vec3 // Expose rotation target for reset
|
|
299
322
|
initial_computed_zoom?: number // Expose initial zoom for reset
|
|
@@ -322,13 +345,9 @@
|
|
|
322
345
|
)
|
|
323
346
|
let pulse_opacity = $derived(0.15 + 0.25 * pulse.unit)
|
|
324
347
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
camera = threlte.camera.current
|
|
329
|
-
if (threlte.renderer) {
|
|
330
|
-
Object.assign(threlte.renderer.domElement, { __renderer: threlte.renderer })
|
|
331
|
-
}
|
|
348
|
+
bind_renderer((threlte_scene, threlte_camera) => {
|
|
349
|
+
scene = threlte_scene
|
|
350
|
+
camera = threlte_camera
|
|
332
351
|
})
|
|
333
352
|
|
|
334
353
|
// Expose rotation target for external reset
|
|
@@ -737,6 +756,27 @@
|
|
|
737
756
|
return true
|
|
738
757
|
}
|
|
739
758
|
|
|
759
|
+
// Pointer props (hover + select) shared by instanced atoms and partial-occupancy
|
|
760
|
+
// hit targets. is_edit_image disables interaction for ghosted PBC image atoms.
|
|
761
|
+
const atom_pointer_props = (site_idx: number, is_edit_image: boolean) => ({
|
|
762
|
+
...atom_hover_props(site_idx, is_edit_image),
|
|
763
|
+
onpointerdown(event: PointerEvent) {
|
|
764
|
+
if (is_edit_image || measure_mode !== `edit-bonds` || bond_edit_mode !== `add`) return
|
|
765
|
+
select_edit_bonds_site(site_idx, event)
|
|
766
|
+
},
|
|
767
|
+
onclick(event: MouseEvent) {
|
|
768
|
+
if (is_edit_image) return
|
|
769
|
+
if (measure_mode === `edit-bonds`) {
|
|
770
|
+
if (bond_edit_mode !== `add`) return
|
|
771
|
+
if (skip_duplicate_edit_bonds_click(site_idx)) {
|
|
772
|
+
event.stopPropagation()
|
|
773
|
+
return
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
toggle_selection(site_idx, event)
|
|
777
|
+
},
|
|
778
|
+
})
|
|
779
|
+
|
|
740
780
|
function toggle_selection(site_index: number, evt?: Event) {
|
|
741
781
|
evt?.stopPropagation?.()
|
|
742
782
|
const event_with_native = evt as Event & { nativeEvent?: unknown } | undefined
|
|
@@ -852,7 +892,7 @@
|
|
|
852
892
|
|
|
853
893
|
let rotation_target = $derived(
|
|
854
894
|
lattice
|
|
855
|
-
?
|
|
895
|
+
? math.scale(math.add(...lattice.matrix), 0.5)
|
|
856
896
|
: structure
|
|
857
897
|
? get_center_of_mass(structure)
|
|
858
898
|
: [0, 0, 0] as Vec3,
|
|
@@ -923,16 +963,43 @@
|
|
|
923
963
|
camera_position = [distance, distance * 0.3, distance * 0.8]
|
|
924
964
|
}
|
|
925
965
|
})
|
|
966
|
+
// Whether a never|always|crystals|molecules setting applies to the current structure
|
|
967
|
+
const applies_to_structure = (when: ShowBonds): boolean =>
|
|
968
|
+
when === `always` ||
|
|
969
|
+
(when === `crystals` && Boolean(lattice)) ||
|
|
970
|
+
(when === `molecules` && !lattice)
|
|
971
|
+
|
|
972
|
+
// Declutter while a symmetry-element overlay actually draws something (elements present
|
|
973
|
+
// AND an enabled kind among them): hide coordination polyhedra/bonds and shrink atoms so
|
|
974
|
+
// axes/planes/centers stay readable. Gating on visibility (not just `symmetry_elements`)
|
|
975
|
+
// avoids hiding everything when nothing renders in its place — e.g. an inversion-only
|
|
976
|
+
// cell under the rotation-only default. Pure derived overrides: the configured
|
|
977
|
+
// appearance returns untouched the moment the overlay goes away.
|
|
978
|
+
const declutter_active = $derived(
|
|
979
|
+
symmetry_declutter &&
|
|
980
|
+
has_visible_symmetry_overlay(symmetry_elements, symmetry_elements_props.show_kinds),
|
|
981
|
+
)
|
|
982
|
+
const effective_show_polyhedra: ShowBonds = $derived(
|
|
983
|
+
declutter_active ? `never` : show_polyhedra,
|
|
984
|
+
)
|
|
985
|
+
// Calculated bonds are hidden in declutter mode (only their cylinders — bond_pairs
|
|
986
|
+
// stay computed so tooltips and manually added bonds keep working)
|
|
987
|
+
const effective_show_bonds: ShowBonds = $derived(
|
|
988
|
+
declutter_active ? `never` : show_bonds,
|
|
989
|
+
)
|
|
990
|
+
const effective_atom_radius = $derived(declutter_active ? atom_radius * 0.6 : atom_radius)
|
|
991
|
+
|
|
926
992
|
$effect(() => {
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
993
|
+
// Bonds are computed when either bond rendering or polyhedra need them. The
|
|
994
|
+
// raw/effective mix is deliberate: RAW show_bonds keeps bond_pairs available
|
|
995
|
+
// during symmetry declutter (cylinders hide via effective_show_bonds in
|
|
996
|
+
// bonds_to_render, but tooltips + manually added bonds still need the data),
|
|
997
|
+
// while EFFECTIVE show_polyhedra skips computing bonds whose only consumer —
|
|
998
|
+
// the polyhedra $derived below, gated on the same effective value — won't run.
|
|
999
|
+
const want_bonds = applies_to_structure(show_bonds)
|
|
1000
|
+
const want_polyhedra = applies_to_structure(effective_show_polyhedra)
|
|
1001
|
+
if (structure && (want_bonds || want_polyhedra)) {
|
|
1002
|
+
bond_pairs = BONDING_STRATEGIES[bonding_strategy](structure, bonding_options)
|
|
936
1003
|
} else bond_pairs = []
|
|
937
1004
|
})
|
|
938
1005
|
|
|
@@ -957,9 +1024,16 @@
|
|
|
957
1024
|
return total_occu > 0 ? weighted_sum / total_occu : 1
|
|
958
1025
|
}
|
|
959
1026
|
|
|
1027
|
+
// Disordered sites are often stored as separate split sites (one species each)
|
|
1028
|
+
// at the same position; merge_split_partial_sites groups them into one render
|
|
1029
|
+
// site whose `species` holds every element. Shared by atom rendering and the
|
|
1030
|
+
// hover tooltip so it lists all elements, not just the majority one.
|
|
1031
|
+
let render_sites = $derived(
|
|
1032
|
+
structure?.sites ? merge_split_partial_sites(structure.sites, hidden_elements) : [],
|
|
1033
|
+
)
|
|
1034
|
+
|
|
960
1035
|
let atom_data = $derived.by(() => {
|
|
961
|
-
if (!show_atoms
|
|
962
|
-
const render_sites = merge_split_partial_sites(structure.sites, hidden_elements)
|
|
1036
|
+
if (!show_atoms) return []
|
|
963
1037
|
return render_sites.flatMap(({ site_idx, site, is_image_atom }) => {
|
|
964
1038
|
const orig_idx = get_orig_site_idx(site, site_idx)
|
|
965
1039
|
|
|
@@ -967,12 +1041,26 @@
|
|
|
967
1041
|
const prop_val = property_colors?.values[orig_idx]
|
|
968
1042
|
if (prop_val !== undefined && hidden_prop_vals.has(prop_val)) return []
|
|
969
1043
|
|
|
1044
|
+
// Optionally hide atoms at the center of a rendered polyhedron
|
|
1045
|
+
if (polyhedra_hide_center_atoms && polyhedra_center_site_idxs.has(site_idx)) {
|
|
1046
|
+
return []
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
// Phase-2 PBC images exist only to complete bonds/coordination polyhedra at
|
|
1050
|
+
// cell faces. When neither renders (polyhedra toggled off, symmetry declutter,
|
|
1051
|
+
// …) they'd float disconnected outside the cell — hide them.
|
|
1052
|
+
if (
|
|
1053
|
+
site.properties?.completion_image &&
|
|
1054
|
+
!applies_to_structure(effective_show_bonds) &&
|
|
1055
|
+
!applies_to_structure(effective_show_polyhedra)
|
|
1056
|
+
) return []
|
|
1057
|
+
|
|
970
1058
|
// Calculate radius: same_size > site override > element override > default
|
|
971
1059
|
// All radii scale uniformly with atom_radius for consistent slider behavior
|
|
972
1060
|
const base_radius = same_size_atoms
|
|
973
1061
|
? 1
|
|
974
1062
|
: site_radius_overrides?.get(site_idx) ?? calc_weighted_radius(site)
|
|
975
|
-
const radius = base_radius *
|
|
1063
|
+
const radius = base_radius * effective_atom_radius
|
|
976
1064
|
|
|
977
1065
|
// Use property color if available (e.g. coordination number, Wyckoff position)
|
|
978
1066
|
// Otherwise, each species gets its own element color (important for disordered sites)
|
|
@@ -1079,13 +1167,106 @@
|
|
|
1079
1167
|
return [...calculated, ...added]
|
|
1080
1168
|
})
|
|
1081
1169
|
|
|
1170
|
+
// Bonds drawn as cylinders. When show_bonds doesn't apply, calculated bonds are
|
|
1171
|
+
// hidden but manually added bonds stay visible (bond_pairs may still be computed
|
|
1172
|
+
// for polyhedra, so this can't rely on bond_pairs being empty).
|
|
1173
|
+
let bonds_to_render = $derived.by(() => {
|
|
1174
|
+
if (applies_to_structure(effective_show_bonds)) return filtered_bond_pairs
|
|
1175
|
+
const added_keys = new Set(added_bonds.map(bond_key_for))
|
|
1176
|
+
return filtered_bond_pairs.filter((bond) => added_keys.has(bond_key_for(bond)))
|
|
1177
|
+
})
|
|
1178
|
+
|
|
1082
1179
|
let editable_bond_pairs = $derived(
|
|
1083
|
-
bond_edits_enabled ?
|
|
1180
|
+
bond_edits_enabled ? bonds_to_render.filter(can_edit_bond) : [],
|
|
1181
|
+
)
|
|
1182
|
+
|
|
1183
|
+
// Coordination polyhedra around cation-like centers, derived from the same
|
|
1184
|
+
// (edited, filtered) bond graph as rendered bonds so the two never disagree.
|
|
1185
|
+
// Colors are resolved in polyhedra_buffers below, so color-scheme/mode changes
|
|
1186
|
+
// never recompute the hull geometry.
|
|
1187
|
+
let polyhedra: Polyhedron[] = $derived.by(() => {
|
|
1188
|
+
if (
|
|
1189
|
+
!structure?.sites || dragging_atoms ||
|
|
1190
|
+
!applies_to_structure(effective_show_polyhedra) ||
|
|
1191
|
+
filtered_bond_pairs.length === 0
|
|
1192
|
+
) return []
|
|
1193
|
+
return compute_polyhedra(structure, filtered_bond_pairs, {
|
|
1194
|
+
min_neighbors: polyhedra_min_neighbors,
|
|
1195
|
+
max_neighbors: polyhedra_max_neighbors,
|
|
1196
|
+
excluded_center_elements: polyhedra_excluded_elements,
|
|
1197
|
+
included_center_elements: polyhedra_included_elements,
|
|
1198
|
+
})
|
|
1199
|
+
})
|
|
1200
|
+
|
|
1201
|
+
// Color of a site: property color (coordination/Wyckoff modes) or element color
|
|
1202
|
+
const polyhedra_site_color = (site_idx: number): string => {
|
|
1203
|
+
const site = structure?.sites[site_idx]
|
|
1204
|
+
const orig_idx = get_orig_site_idx(site, site_idx)
|
|
1205
|
+
const element = get_majority_element(site)
|
|
1206
|
+
return property_colors?.colors[orig_idx] ??
|
|
1207
|
+
(element && colors.element?.[element]) ?? `#808080`
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
// Separate derived so material-only changes (opacity, edge color) don't rebuild
|
|
1211
|
+
// buffers and color changes don't rebuild hulls
|
|
1212
|
+
let polyhedra_buffers = $derived.by(() => {
|
|
1213
|
+
if (polyhedra.length === 0) return null
|
|
1214
|
+
const get_vertex_color = (poly: Polyhedron, vertex_idx: number): string => {
|
|
1215
|
+
if (polyhedra_color_mode === `uniform`) return polyhedra_color
|
|
1216
|
+
if (polyhedra_color_mode === `center`) {
|
|
1217
|
+
return polyhedra_site_color(poly.center_site_idx)
|
|
1218
|
+
}
|
|
1219
|
+
// 'vertex' (default): each corner takes the color of the atom that forms it
|
|
1220
|
+
return polyhedra_site_color(poly.vertex_site_idxs[vertex_idx])
|
|
1221
|
+
}
|
|
1222
|
+
return merge_polyhedra_buffers(polyhedra, get_vertex_color)
|
|
1223
|
+
})
|
|
1224
|
+
|
|
1225
|
+
let polyhedra_center_site_idxs = $derived(
|
|
1226
|
+
new Set(polyhedra.map((poly) => poly.center_site_idx)),
|
|
1084
1227
|
)
|
|
1085
1228
|
|
|
1229
|
+
// Publish which elements currently anchor polyhedra (consumed by controls so
|
|
1230
|
+
// per-element toggles reflect the actual render state incl. spectator hiding)
|
|
1231
|
+
$effect(() => {
|
|
1232
|
+
const elems = [...new Set(polyhedra.map((poly) => poly.center_element))].sort()
|
|
1233
|
+
if (elems.join(`,`) !== polyhedra_rendered_elements.join(`,`)) {
|
|
1234
|
+
polyhedra_rendered_elements = elems
|
|
1235
|
+
}
|
|
1236
|
+
})
|
|
1237
|
+
|
|
1238
|
+
// Geometries with proper disposal on dependency change (same pattern as ReferencePlane)
|
|
1239
|
+
const buffer_geometry = (attrs: Record<string, Float32Array>): BufferGeometry => {
|
|
1240
|
+
const geo = new BufferGeometry()
|
|
1241
|
+
for (const [name, array] of Object.entries(attrs)) {
|
|
1242
|
+
geo.setAttribute(name, new BufferAttribute(array, 3))
|
|
1243
|
+
}
|
|
1244
|
+
return geo
|
|
1245
|
+
}
|
|
1246
|
+
let polyhedra_geometry: BufferGeometry | null = $state(null)
|
|
1247
|
+
$effect(() => {
|
|
1248
|
+
let geo: BufferGeometry | null = null
|
|
1249
|
+
if (polyhedra_buffers && polyhedra_buffers.triangle_count > 0) {
|
|
1250
|
+
const { positions: position, colors: color } = polyhedra_buffers
|
|
1251
|
+
geo = buffer_geometry({ position, color })
|
|
1252
|
+
geo.computeVertexNormals() // non-indexed -> per-face normals (flat shading)
|
|
1253
|
+
}
|
|
1254
|
+
polyhedra_geometry = geo
|
|
1255
|
+
return () => geo?.dispose()
|
|
1256
|
+
})
|
|
1257
|
+
|
|
1258
|
+
let polyhedra_edge_geometry: BufferGeometry | null = $state(null)
|
|
1259
|
+
$effect(() => {
|
|
1260
|
+
const geo = polyhedra_show_edges && polyhedra_buffers && polyhedra_buffers.edge_count > 0
|
|
1261
|
+
? buffer_geometry({ position: polyhedra_buffers.edge_positions })
|
|
1262
|
+
: null
|
|
1263
|
+
polyhedra_edge_geometry = geo
|
|
1264
|
+
return () => geo?.dispose()
|
|
1265
|
+
})
|
|
1266
|
+
|
|
1086
1267
|
let smart_site_label_offsets = $derived.by(() => {
|
|
1087
1268
|
const offsets = new SvelteMap<number, Vec3>()
|
|
1088
|
-
if (
|
|
1269
|
+
if (bonds_to_render.length === 0) return offsets
|
|
1089
1270
|
|
|
1090
1271
|
const bond_directions_by_site = new SvelteMap<number, Vec3[]>()
|
|
1091
1272
|
const add_bond_direction = (site_idx: number, pos_1: Vec3, pos_2: Vec3) => {
|
|
@@ -1100,7 +1281,7 @@
|
|
|
1100
1281
|
])
|
|
1101
1282
|
}
|
|
1102
1283
|
|
|
1103
|
-
for (const { site_idx_1, site_idx_2, pos_1, pos_2 } of
|
|
1284
|
+
for (const { site_idx_1, site_idx_2, pos_1, pos_2 } of bonds_to_render) {
|
|
1104
1285
|
add_bond_direction(site_idx_1, pos_1, pos_2)
|
|
1105
1286
|
add_bond_direction(site_idx_2, pos_2, pos_1)
|
|
1106
1287
|
}
|
|
@@ -1111,7 +1292,7 @@
|
|
|
1111
1292
|
})
|
|
1112
1293
|
|
|
1113
1294
|
let instanced_bond_groups = $derived.by(() => {
|
|
1114
|
-
if (!structure?.sites ||
|
|
1295
|
+
if (!structure?.sites || bonds_to_render.length === 0) return []
|
|
1115
1296
|
|
|
1116
1297
|
const group = {
|
|
1117
1298
|
thickness: bond_thickness,
|
|
@@ -1124,7 +1305,7 @@
|
|
|
1124
1305
|
}[],
|
|
1125
1306
|
}
|
|
1126
1307
|
|
|
1127
|
-
for (const bond_data of
|
|
1308
|
+
for (const bond_data of bonds_to_render) {
|
|
1128
1309
|
const site_a = structure.sites[bond_data.site_idx_1]
|
|
1129
1310
|
const site_b = structure.sites[bond_data.site_idx_2]
|
|
1130
1311
|
|
|
@@ -1154,6 +1335,24 @@
|
|
|
1154
1335
|
return map
|
|
1155
1336
|
})
|
|
1156
1337
|
|
|
1338
|
+
// Partial-occupancy atoms render as separate wedge (lune) meshes that converge
|
|
1339
|
+
// to a point at the sphere's poles, leaving the ball hard to hover from some
|
|
1340
|
+
// angles. Give each such site one invisible full-sphere hit target so it's as
|
|
1341
|
+
// reliably hoverable as an ordered atom (single solid sphere). One per site.
|
|
1342
|
+
let partial_hit_targets = $derived.by(() => {
|
|
1343
|
+
const targets = new SvelteMap<number, EditableAtomHitTarget & { is_image_atom: boolean }>()
|
|
1344
|
+
for (const atom of atom_data) {
|
|
1345
|
+
if (!atom.has_partial_occupancy || targets.has(atom.site_idx)) continue
|
|
1346
|
+
targets.set(atom.site_idx, {
|
|
1347
|
+
site_idx: atom.site_idx,
|
|
1348
|
+
position: atom.position,
|
|
1349
|
+
radius: atom.radius,
|
|
1350
|
+
is_image_atom: atom.is_image_atom,
|
|
1351
|
+
})
|
|
1352
|
+
}
|
|
1353
|
+
return [...targets.values()]
|
|
1354
|
+
})
|
|
1355
|
+
|
|
1157
1356
|
let editable_atom_hit_targets = $derived.by(() => {
|
|
1158
1357
|
if (
|
|
1159
1358
|
measure_mode !== `edit-bonds` ||
|
|
@@ -1183,7 +1382,7 @@
|
|
|
1183
1382
|
? site_radius_overrides?.get(site_idx)
|
|
1184
1383
|
: undefined
|
|
1185
1384
|
const base_radius = same_size_atoms ? 1 : override ?? calc_weighted_radius(site)
|
|
1186
|
-
return base_radius *
|
|
1385
|
+
return base_radius * effective_atom_radius
|
|
1187
1386
|
}
|
|
1188
1387
|
|
|
1189
1388
|
// Interpolate between spin-down (#3498db blue) and spin-up (#e74c3c red)
|
|
@@ -1259,9 +1458,9 @@
|
|
|
1259
1458
|
const offsets = new SvelteMap<string, Vec3>()
|
|
1260
1459
|
for (const [idx, key] of site_keys.entries()) {
|
|
1261
1460
|
const angle = (2 * Math.PI * idx) / n_keys
|
|
1262
|
-
const dx = math.scale(u_vec, gap_abs * Math.cos(angle))
|
|
1263
|
-
const dy = math.scale(v_vec, gap_abs * Math.sin(angle))
|
|
1264
|
-
offsets.set(key, math.add(dx, dy)
|
|
1461
|
+
const dx = math.scale(u_vec, gap_abs * Math.cos(angle))
|
|
1462
|
+
const dy = math.scale(v_vec, gap_abs * Math.sin(angle))
|
|
1463
|
+
offsets.set(key, math.add(dx, dy))
|
|
1265
1464
|
}
|
|
1266
1465
|
return offsets
|
|
1267
1466
|
})
|
|
@@ -1315,7 +1514,7 @@
|
|
|
1315
1514
|
}
|
|
1316
1515
|
|
|
1317
1516
|
const offset = site_offsets?.[site_idx]?.get(key)
|
|
1318
|
-
const position = offset ? math.add(site.xyz, offset)
|
|
1517
|
+
const position = offset ? math.add(site.xyz, offset) : site.xyz
|
|
1319
1518
|
const arrow_vec = vector_normalize ? math.normalize_vec(vec) : vec
|
|
1320
1519
|
|
|
1321
1520
|
return {
|
|
@@ -1364,57 +1563,29 @@
|
|
|
1364
1563
|
),
|
|
1365
1564
|
)
|
|
1366
1565
|
|
|
1367
|
-
let
|
|
1368
|
-
|
|
1369
|
-
[...AXIS_COLORS, ...NEG_AXIS_COLORS].map(([axis, color, hover_color]) => [
|
|
1370
|
-
axis,
|
|
1371
|
-
{
|
|
1372
|
-
color,
|
|
1373
|
-
labelColor: `#111`,
|
|
1374
|
-
opacity: axis.startsWith(`n`) ? 0.9 : 0.8,
|
|
1375
|
-
hover: {
|
|
1376
|
-
color: hover_color,
|
|
1377
|
-
labelColor: `#222222`,
|
|
1378
|
-
opacity: axis.startsWith(`n`) ? 1 : 0.9,
|
|
1379
|
-
},
|
|
1380
|
-
},
|
|
1381
|
-
]),
|
|
1382
|
-
)
|
|
1383
|
-
return {
|
|
1384
|
-
background: { enabled: false },
|
|
1385
|
-
className: `responsive-gizmo`,
|
|
1386
|
-
...axis_options,
|
|
1387
|
-
...(typeof gizmo === `boolean` ? {} : gizmo),
|
|
1388
|
-
offset: { left: 5, bottom: 5 },
|
|
1389
|
-
}
|
|
1390
|
-
})
|
|
1391
|
-
|
|
1392
|
-
let orbit_controls_props = $derived({
|
|
1393
|
-
position: [0, 0, 0],
|
|
1394
|
-
enableRotate: rotate_speed > 0,
|
|
1395
|
-
rotateSpeed: rotate_speed,
|
|
1396
|
-
enableZoom: zoom_speed > 0,
|
|
1397
|
-
zoomSpeed: camera_projection === `orthographic` ? zoom_speed * 2 : zoom_speed,
|
|
1398
|
-
zoomToCursor: zoom_to_cursor,
|
|
1399
|
-
enablePan: pan_speed > 0,
|
|
1400
|
-
panSpeed: pan_speed,
|
|
1566
|
+
let orbit_controls_props = $derived(build_orbit_props({
|
|
1567
|
+
camera_projection,
|
|
1401
1568
|
target: camera_target ?? rotation_target,
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1569
|
+
rotate_speed,
|
|
1570
|
+
zoom_speed,
|
|
1571
|
+
zoom_to_cursor,
|
|
1572
|
+
pan_speed,
|
|
1573
|
+
max_zoom,
|
|
1574
|
+
min_zoom,
|
|
1575
|
+
auto_rotate,
|
|
1576
|
+
rotation_damping,
|
|
1577
|
+
set_camera_is_moving: (moving) => (camera_is_moving = moving),
|
|
1578
|
+
// Close hover tooltips + bond context menu while the camera moves. Only hide the
|
|
1579
|
+
// VISIBLE menu (not bond_context_target): clicking a menu button fires this
|
|
1580
|
+
// orbit-controls start handler before the button's own handler runs, which still
|
|
1581
|
+
// needs the target bond to apply the edit (see bond_context_target comment).
|
|
1582
|
+
onstart_extra: () => {
|
|
1410
1583
|
cancel_atom_hover_clear()
|
|
1411
1584
|
hovered_idx = null
|
|
1585
|
+
hovered_bond_key = null
|
|
1412
1586
|
bond_context_menu = null
|
|
1413
1587
|
},
|
|
1414
|
-
|
|
1415
|
-
camera_is_moving = false
|
|
1416
|
-
},
|
|
1417
|
-
})
|
|
1588
|
+
}))
|
|
1418
1589
|
|
|
1419
1590
|
let measure_line_color = $derived.by(() => {
|
|
1420
1591
|
if (typeof window === `undefined`) return
|
|
@@ -1491,31 +1662,17 @@
|
|
|
1491
1662
|
</extras.HTML>
|
|
1492
1663
|
{/snippet}
|
|
1493
1664
|
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
</T.PerspectiveCamera>
|
|
1506
|
-
{:else}
|
|
1507
|
-
<T.OrthographicCamera
|
|
1508
|
-
makeDefault
|
|
1509
|
-
position={camera_position}
|
|
1510
|
-
zoom={computed_zoom}
|
|
1511
|
-
near={-100}
|
|
1512
|
-
far={camera_far}
|
|
1513
|
-
>
|
|
1514
|
-
<extras.OrbitControls bind:ref={orbit_controls} {...orbit_controls_props}>
|
|
1515
|
-
{#if gizmo}<extras.Gizmo {...gizmo_props} />{/if}
|
|
1516
|
-
</extras.OrbitControls>
|
|
1517
|
-
</T.OrthographicCamera>
|
|
1518
|
-
{/if}
|
|
1665
|
+
<SceneCamera
|
|
1666
|
+
{camera_projection}
|
|
1667
|
+
position={camera_position}
|
|
1668
|
+
{fov}
|
|
1669
|
+
zoom={computed_zoom}
|
|
1670
|
+
near={camera_near}
|
|
1671
|
+
far={camera_far}
|
|
1672
|
+
orbit_props={orbit_controls_props}
|
|
1673
|
+
{gizmo}
|
|
1674
|
+
bind:orbit_controls
|
|
1675
|
+
/>
|
|
1519
1676
|
|
|
1520
1677
|
<T.DirectionalLight position={[3, 10, 10]} intensity={directional_light} />
|
|
1521
1678
|
<T.AmbientLight intensity={ambient_light} />
|
|
@@ -1545,28 +1702,7 @@
|
|
|
1545
1702
|
<extras.Instance
|
|
1546
1703
|
position={atom.position}
|
|
1547
1704
|
scale={atom.radius}
|
|
1548
|
-
{...
|
|
1549
|
-
onpointerdown={(event: PointerEvent) => {
|
|
1550
|
-
if (
|
|
1551
|
-
edit_mode_image ||
|
|
1552
|
-
measure_mode !== `edit-bonds` ||
|
|
1553
|
-
bond_edit_mode !== `add`
|
|
1554
|
-
) {
|
|
1555
|
-
return
|
|
1556
|
-
}
|
|
1557
|
-
select_edit_bonds_site(atom.site_idx, event)
|
|
1558
|
-
}}
|
|
1559
|
-
onclick={(event: MouseEvent) => {
|
|
1560
|
-
if (edit_mode_image) return
|
|
1561
|
-
if (measure_mode === `edit-bonds`) {
|
|
1562
|
-
if (bond_edit_mode !== `add`) return
|
|
1563
|
-
if (skip_duplicate_edit_bonds_click(atom.site_idx)) {
|
|
1564
|
-
event.stopPropagation()
|
|
1565
|
-
return
|
|
1566
|
-
}
|
|
1567
|
-
}
|
|
1568
|
-
toggle_selection(atom.site_idx, event)
|
|
1569
|
-
}}
|
|
1705
|
+
{...atom_pointer_props(atom.site_idx, edit_mode_image)}
|
|
1570
1706
|
/>
|
|
1571
1707
|
{/each}
|
|
1572
1708
|
</extras.InstancedMesh>
|
|
@@ -1579,32 +1715,9 @@
|
|
|
1579
1715
|
}
|
|
1580
1716
|
{@const partial_edit_image = measure_mode === `edit-atoms` && atom.is_image_atom}
|
|
1581
1717
|
{@const ghost_opacity = partial_edit_image ? 0.5 : 1}
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
{...atom_hover_props(atom.site_idx, partial_edit_image)}
|
|
1586
|
-
onpointerdown={(event: PointerEvent) => {
|
|
1587
|
-
if (
|
|
1588
|
-
partial_edit_image ||
|
|
1589
|
-
measure_mode !== `edit-bonds` ||
|
|
1590
|
-
bond_edit_mode !== `add`
|
|
1591
|
-
) {
|
|
1592
|
-
return
|
|
1593
|
-
}
|
|
1594
|
-
select_edit_bonds_site(atom.site_idx, event)
|
|
1595
|
-
}}
|
|
1596
|
-
onclick={(event: MouseEvent) => {
|
|
1597
|
-
if (partial_edit_image) return
|
|
1598
|
-
if (measure_mode === `edit-bonds`) {
|
|
1599
|
-
if (bond_edit_mode !== `add`) return
|
|
1600
|
-
if (skip_duplicate_edit_bonds_click(atom.site_idx)) {
|
|
1601
|
-
event.stopPropagation()
|
|
1602
|
-
return
|
|
1603
|
-
}
|
|
1604
|
-
}
|
|
1605
|
-
toggle_selection(atom.site_idx, event)
|
|
1606
|
-
}}
|
|
1607
|
-
>
|
|
1718
|
+
<!-- Visual only: pointer interaction handled by the invisible full-sphere
|
|
1719
|
+
hit targets below (wedge meshes leave gaps at the poles). -->
|
|
1720
|
+
<T.Group position={atom.position} scale={atom.radius}>
|
|
1608
1721
|
{@const partial_color = partial_edit_image
|
|
1609
1722
|
? desaturate(atom.color)
|
|
1610
1723
|
: atom.color}
|
|
@@ -1625,7 +1738,7 @@
|
|
|
1625
1738
|
/>
|
|
1626
1739
|
</T.Mesh>
|
|
1627
1740
|
|
|
1628
|
-
{#if atom.
|
|
1741
|
+
{#if atom.render_start_cap}
|
|
1629
1742
|
<T.Mesh rotation={[0, atom.start_phi, 0]}>
|
|
1630
1743
|
<T.CircleGeometry
|
|
1631
1744
|
args={[
|
|
@@ -1643,7 +1756,7 @@
|
|
|
1643
1756
|
/>
|
|
1644
1757
|
</T.Mesh>
|
|
1645
1758
|
{/if}
|
|
1646
|
-
{#if atom.
|
|
1759
|
+
{#if atom.render_end_cap}
|
|
1647
1760
|
<T.Mesh rotation={[0, atom.end_phi, 0]}>
|
|
1648
1761
|
<T.CircleGeometry
|
|
1649
1762
|
args={[
|
|
@@ -1670,6 +1783,20 @@
|
|
|
1670
1783
|
{/if}
|
|
1671
1784
|
{/each}
|
|
1672
1785
|
|
|
1786
|
+
<!-- Invisible full-sphere hit targets for partial-occupancy sites so the
|
|
1787
|
+
whole ball is hoverable/clickable (wedge meshes leave gaps at the poles). -->
|
|
1788
|
+
{#each partial_hit_targets as hit (hit.site_idx)}
|
|
1789
|
+
{@const hit_edit_image = measure_mode === `edit-atoms` && hit.is_image_atom}
|
|
1790
|
+
<T.Mesh
|
|
1791
|
+
position={hit.position}
|
|
1792
|
+
scale={hit.radius}
|
|
1793
|
+
{...atom_pointer_props(hit.site_idx, hit_edit_image)}
|
|
1794
|
+
>
|
|
1795
|
+
<T.SphereGeometry args={[0.5, sphere_segments, sphere_segments]} />
|
|
1796
|
+
<T.MeshBasicMaterial transparent opacity={0} depthWrite={false} />
|
|
1797
|
+
</T.Mesh>
|
|
1798
|
+
{/each}
|
|
1799
|
+
|
|
1673
1800
|
<!-- Site labels/indices for instanced atoms -->
|
|
1674
1801
|
{#if show_site_labels || show_site_indices}
|
|
1675
1802
|
{#each unique_instanced_atoms as atom (atom.site_idx)}
|
|
@@ -1696,6 +1823,32 @@
|
|
|
1696
1823
|
{/each}
|
|
1697
1824
|
{/if}
|
|
1698
1825
|
|
|
1826
|
+
<!-- Coordination polyhedra: all faces in one merged mesh, edges in one
|
|
1827
|
+
LineSegments (1-2 draw calls regardless of supercell size) -->
|
|
1828
|
+
{#if polyhedra_geometry}
|
|
1829
|
+
<T.Mesh geometry={polyhedra_geometry} frustumCulled={false} raycast={() => null}>
|
|
1830
|
+
<!-- depthWrite when mostly opaque: VESTA-like occlusion between polyhedra;
|
|
1831
|
+
fully translucent settings fall back to see-through blending -->
|
|
1832
|
+
<T.MeshStandardMaterial
|
|
1833
|
+
vertexColors
|
|
1834
|
+
transparent={polyhedra_opacity < 1}
|
|
1835
|
+
opacity={polyhedra_opacity}
|
|
1836
|
+
side={DoubleSide}
|
|
1837
|
+
depthWrite={polyhedra_opacity >= 0.65}
|
|
1838
|
+
flatShading
|
|
1839
|
+
/>
|
|
1840
|
+
</T.Mesh>
|
|
1841
|
+
{#if polyhedra_edge_geometry}
|
|
1842
|
+
<T.LineSegments
|
|
1843
|
+
geometry={polyhedra_edge_geometry}
|
|
1844
|
+
frustumCulled={false}
|
|
1845
|
+
raycast={() => null}
|
|
1846
|
+
>
|
|
1847
|
+
<T.LineBasicMaterial color={polyhedra_edge_color} />
|
|
1848
|
+
</T.LineSegments>
|
|
1849
|
+
{/if}
|
|
1850
|
+
{/if}
|
|
1851
|
+
|
|
1699
1852
|
<!-- Clickable bond hit-test cylinders in edit-bonds mode -->
|
|
1700
1853
|
{#if measure_mode === `edit-bonds` && editable_bond_pairs.length > 0}
|
|
1701
1854
|
{#each editable_bond_pairs as
|
|
@@ -1910,8 +2063,8 @@
|
|
|
1910
2063
|
{@const site = structure.sites[site_index]}
|
|
1911
2064
|
{#if site}
|
|
1912
2065
|
<!-- shift selected site labels down to avoid overlapping regular site labels-->
|
|
1913
|
-
{@const selection_offset = math.add(site_label_offset, [0, -0.5, 0])}
|
|
1914
|
-
{@const pos = math.add(site.xyz, selection_offset)
|
|
2066
|
+
{@const selection_offset = math.add<Vec3>(site_label_offset, [0, -0.5, 0])}
|
|
2067
|
+
{@const pos = math.add(site.xyz, selection_offset)}
|
|
1915
2068
|
<extras.HTML center position={pos}>
|
|
1916
2069
|
<span class="selection-label">{loop_idx + 1}</span>
|
|
1917
2070
|
</extras.HTML>
|
|
@@ -1952,10 +2105,13 @@
|
|
|
1952
2105
|
.map(([elem, count]) => `${elem}: ${count}`)
|
|
1953
2106
|
return ` (${parts.join(`, `)})`
|
|
1954
2107
|
})()}
|
|
2108
|
+
{@const tooltip_species =
|
|
2109
|
+
render_sites.find((rs) => rs.site_idx === hovered_idx)?.site.species ??
|
|
2110
|
+
hovered_site.species ?? []}
|
|
1955
2111
|
<CanvasTooltip position={hovered_site.xyz}>
|
|
1956
2112
|
<!-- Element symbols with occupancies for disordered sites -->
|
|
1957
2113
|
<div class="elements">
|
|
1958
|
-
{#each
|
|
2114
|
+
{#each tooltip_species as
|
|
1959
2115
|
{ element, occu, oxidation_state: oxi_state },
|
|
1960
2116
|
idx
|
|
1961
2117
|
(`${element ?? ``}-${occu ?? ``}-${oxi_state ?? ``}-${idx}`)
|
|
@@ -1964,16 +2120,17 @@
|
|
|
1964
2120
|
elem.symbol === element
|
|
1965
2121
|
)?.name ??
|
|
1966
2122
|
``}
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
2123
|
+
<span class="species">
|
|
2124
|
+
{#if occu !== 1}<span class="occupancy">{
|
|
2125
|
+
format_num(occu, `.3~f`)
|
|
2126
|
+
}</span>{/if}
|
|
2127
|
+
<strong>
|
|
2128
|
+
{element}{#if oxi_state != null && oxi_state !== 0}<sup>{Math.abs(
|
|
2129
|
+
oxi_state,
|
|
2130
|
+
)}{oxi_state > 0 ? `+` : `−`}</sup>{/if}
|
|
2131
|
+
</strong>
|
|
2132
|
+
{#if element_name}<span class="elem-name">{element_name}</span>{/if}
|
|
2133
|
+
</span>
|
|
1977
2134
|
{/each}
|
|
1978
2135
|
</div>
|
|
1979
2136
|
<div class="coordinates fractional">abc: ({abc})</div>
|
|
@@ -1986,6 +2143,13 @@
|
|
|
1986
2143
|
|
|
1987
2144
|
{#if visual_lattice}
|
|
1988
2145
|
<Lattice matrix={visual_lattice.matrix} {...lattice_props} />
|
|
2146
|
+
{#if symmetry_elements.length > 0}
|
|
2147
|
+
<SymmetryElements
|
|
2148
|
+
elements={symmetry_elements}
|
|
2149
|
+
lattice={visual_lattice.matrix}
|
|
2150
|
+
{...symmetry_elements_props}
|
|
2151
|
+
/>
|
|
2152
|
+
{/if}
|
|
1989
2153
|
{/if}
|
|
1990
2154
|
|
|
1991
2155
|
<!-- TransformControls for editing atoms in edit-atoms mode -->
|
|
@@ -2163,10 +2327,6 @@
|
|
|
2163
2327
|
</T.Group>
|
|
2164
2328
|
|
|
2165
2329
|
<style>
|
|
2166
|
-
:global(.structure .responsive-gizmo) {
|
|
2167
|
-
width: clamp(70px, 18cqmin, 100px) !important;
|
|
2168
|
-
height: clamp(70px, 18cqmin, 100px) !important;
|
|
2169
|
-
}
|
|
2170
2330
|
.atom-label {
|
|
2171
2331
|
background: var(--struct-atom-label-bg, rgba(0, 0, 0, 0.1));
|
|
2172
2332
|
border: 0;
|
|
@@ -2180,6 +2340,13 @@
|
|
|
2180
2340
|
.elements {
|
|
2181
2341
|
margin-bottom: var(--canvas-tooltip-elements-margin);
|
|
2182
2342
|
}
|
|
2343
|
+
.species {
|
|
2344
|
+
display: inline-block;
|
|
2345
|
+
white-space: nowrap;
|
|
2346
|
+
&:not(:first-child) {
|
|
2347
|
+
margin-left: var(--canvas-tooltip-species-gap, 0.5em);
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2183
2350
|
.occupancy {
|
|
2184
2351
|
font-size: var(--canvas-tooltip-occu-font-size);
|
|
2185
2352
|
opacity: var(--canvas-tooltip-occu-opacity);
|