matterviz 0.3.2 → 0.3.4
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/EmptyState.svelte +10 -2
- package/dist/FilePicker.svelte +123 -82
- package/dist/Icon.svelte +18 -12
- package/dist/MillerIndexInput.svelte +27 -21
- package/dist/api/optimade.js +6 -6
- package/dist/app.css +216 -207
- package/dist/brillouin/BrillouinZone.svelte +292 -149
- package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
- package/dist/brillouin/BrillouinZoneExportPane.svelte +69 -42
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
- package/dist/brillouin/BrillouinZoneScene.svelte +275 -163
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneTooltip.svelte +17 -7
- package/dist/brillouin/compute.js +11 -6
- package/dist/chempot-diagram/ChemPotDiagram.svelte +162 -27
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +451 -281
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +2148 -1642
- package/dist/chempot-diagram/ChemPotScene3D.svelte +8 -5
- package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
- package/dist/chempot-diagram/async-compute.svelte.js +77 -0
- package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
- package/dist/chempot-diagram/chempot-worker.js +11 -0
- package/dist/chempot-diagram/color.js +1 -2
- package/dist/chempot-diagram/compute.d.ts +10 -0
- package/dist/chempot-diagram/compute.js +250 -88
- package/dist/chempot-diagram/index.d.ts +2 -1
- package/dist/chempot-diagram/index.js +2 -1
- package/dist/chempot-diagram/temperature.js +8 -9
- package/dist/chempot-diagram/types.d.ts +3 -0
- package/dist/chempot-diagram/types.js +1 -0
- package/dist/colors/index.d.ts +1 -1
- package/dist/colors/index.js +5 -3
- package/dist/composition/BarChart.svelte +128 -55
- package/dist/composition/BubbleChart.svelte +102 -49
- package/dist/composition/Composition.svelte +100 -79
- package/dist/composition/Formula.svelte +108 -62
- package/dist/composition/FormulaFilter.svelte +665 -537
- package/dist/composition/PieChart.svelte +183 -108
- package/dist/composition/format.d.ts +5 -0
- package/dist/composition/format.js +20 -3
- package/dist/composition/parse.js +14 -9
- package/dist/convex-hull/ConvexHull.svelte +93 -40
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull2D.svelte +549 -360
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +1296 -827
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +1004 -688
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullControls.svelte +115 -28
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
- package/dist/convex-hull/ConvexHullStats.svelte +425 -328
- package/dist/convex-hull/ConvexHullTooltip.svelte +40 -16
- package/dist/convex-hull/GasPressureControls.svelte +104 -61
- package/dist/convex-hull/StructurePopup.svelte +25 -4
- package/dist/convex-hull/TemperatureSlider.svelte +45 -25
- package/dist/convex-hull/barycentric-coords.js +13 -7
- package/dist/convex-hull/demo-temperature.js +8 -4
- package/dist/convex-hull/gas-thermodynamics.js +17 -12
- package/dist/convex-hull/helpers.d.ts +9 -0
- package/dist/convex-hull/helpers.js +77 -34
- package/dist/convex-hull/thermodynamics.js +61 -56
- package/dist/convex-hull/types.d.ts +9 -14
- package/dist/convex-hull/types.js +0 -17
- package/dist/coordination/CoordinationBarPlot.svelte +227 -154
- package/dist/element/BohrAtom.svelte +55 -12
- package/dist/element/ElementHeading.svelte +7 -2
- package/dist/element/ElementPhoto.svelte +15 -9
- package/dist/element/ElementStats.svelte +10 -4
- package/dist/element/ElementTile.svelte +137 -73
- package/dist/element/Nucleus.svelte +39 -11
- package/dist/element/data.js +1 -1
- package/dist/feedback/ClickFeedback.svelte +16 -5
- package/dist/feedback/DragOverlay.svelte +10 -2
- package/dist/feedback/Spinner.svelte +4 -2
- package/dist/feedback/StatusMessage.svelte +8 -2
- package/dist/fermi-surface/FermiSlice.svelte +118 -88
- package/dist/fermi-surface/FermiSurface.svelte +328 -187
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +535 -342
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
- package/dist/fermi-surface/compute.js +16 -20
- package/dist/fermi-surface/parse.js +24 -14
- package/dist/fermi-surface/symmetry.js +2 -7
- package/dist/fermi-surface/types.d.ts +3 -5
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +1019 -765
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +1 -1
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +76 -22
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +2 -3
- package/dist/icons.js +47 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/io/decompress.js +1 -1
- package/dist/io/export.d.ts +3 -0
- package/dist/io/export.js +129 -143
- package/dist/io/is-binary.js +2 -3
- package/dist/io/url-drop.js +1 -2
- package/dist/isosurface/Isosurface.svelte +202 -148
- package/dist/isosurface/IsosurfaceControls.svelte +46 -28
- package/dist/isosurface/parse.js +34 -29
- package/dist/isosurface/slice.js +5 -10
- package/dist/isosurface/types.d.ts +2 -1
- package/dist/isosurface/types.js +61 -12
- package/dist/labels.js +11 -8
- package/dist/layout/FullscreenToggle.svelte +11 -2
- package/dist/layout/InfoCard.svelte +38 -6
- package/dist/layout/InfoTag.svelte +63 -32
- package/dist/layout/PropertyFilter.svelte +82 -37
- package/dist/layout/SettingsSection.svelte +85 -55
- package/dist/layout/SubpageGrid.svelte +10 -2
- package/dist/layout/json-tree/JsonNode.svelte +183 -138
- package/dist/layout/json-tree/JsonTree.svelte +499 -413
- package/dist/layout/json-tree/JsonValue.svelte +127 -99
- package/dist/layout/json-tree/utils.js +4 -2
- package/dist/marching-cubes.js +25 -2
- package/dist/math.d.ts +13 -17
- package/dist/math.js +133 -67
- package/dist/overlays/ContextMenu.svelte +65 -40
- package/dist/overlays/DraggablePane.svelte +211 -139
- package/dist/periodic-table/PeriodicTable.svelte +278 -145
- package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
- package/dist/periodic-table/PropertySelect.svelte +25 -7
- package/dist/periodic-table/TableInset.svelte +8 -3
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +446 -309
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramControls.svelte +102 -43
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +63 -40
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +71 -28
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +158 -101
- package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
- package/dist/phase-diagram/build-diagram.js +9 -9
- package/dist/phase-diagram/colors.js +1 -3
- package/dist/phase-diagram/parse.js +10 -9
- package/dist/phase-diagram/svg-to-diagram.js +53 -49
- package/dist/phase-diagram/utils.d.ts +1 -0
- package/dist/phase-diagram/utils.js +80 -25
- package/dist/plot/AxisLabel.svelte +28 -3
- package/dist/plot/BarPlot.svelte +1182 -734
- package/dist/plot/BarPlot.svelte.d.ts +2 -2
- package/dist/plot/BarPlotControls.svelte +31 -5
- package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ColorBar.svelte +479 -329
- package/dist/plot/ColorScaleSelect.svelte +27 -6
- package/dist/plot/ElementScatter.svelte +36 -15
- package/dist/plot/FillArea.svelte +152 -95
- package/dist/plot/Histogram.svelte +934 -571
- package/dist/plot/Histogram.svelte.d.ts +1 -1
- package/dist/plot/HistogramControls.svelte +53 -9
- package/dist/plot/HistogramControls.svelte.d.ts +1 -1
- package/dist/plot/InteractiveAxisLabel.svelte +34 -11
- package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
- package/dist/plot/Line.svelte +63 -28
- package/dist/plot/PlotControls.svelte +157 -114
- package/dist/plot/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/PlotLegend.svelte +174 -91
- package/dist/plot/PlotTooltip.svelte +45 -6
- package/dist/plot/PortalSelect.svelte +175 -147
- package/dist/plot/ReferenceLine.svelte +76 -22
- package/dist/plot/ReferenceLine3D.svelte +132 -107
- package/dist/plot/ReferencePlane.svelte +146 -121
- package/dist/plot/ScatterPlot.svelte +1681 -1091
- package/dist/plot/ScatterPlot.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlot3D.svelte +256 -131
- package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlot3DControls.svelte +113 -63
- package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
- package/dist/plot/ScatterPlot3DScene.svelte +608 -403
- package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlotControls.svelte +65 -25
- package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ScatterPoint.svelte +98 -26
- package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
- package/dist/plot/SpacegroupBarPlot.svelte +142 -85
- package/dist/plot/Surface3D.svelte +159 -108
- package/dist/plot/ZeroLines.svelte +55 -3
- package/dist/plot/ZoomRect.svelte +4 -2
- package/dist/plot/axis-utils.js +1 -3
- package/dist/plot/data-cleaning.js +12 -28
- package/dist/plot/data-transform.js +2 -1
- package/dist/plot/fill-utils.js +2 -0
- package/dist/plot/layout.d.ts +4 -1
- package/dist/plot/layout.js +33 -14
- package/dist/plot/reference-line.d.ts +2 -2
- package/dist/plot/reference-line.js +7 -5
- package/dist/plot/scales.js +24 -36
- package/dist/plot/types.d.ts +11 -23
- package/dist/plot/types.js +6 -11
- package/dist/plot/utils/label-placement.d.ts +32 -15
- package/dist/plot/utils/label-placement.js +227 -66
- package/dist/plot/utils/series-visibility.js +2 -3
- package/dist/rdf/RdfPlot.svelte +143 -91
- package/dist/rdf/calc-rdf.js +4 -5
- package/dist/sanitize.d.ts +4 -0
- package/dist/sanitize.js +107 -0
- package/dist/settings.d.ts +18 -6
- package/dist/settings.js +46 -16
- package/dist/spectral/Bands.svelte +632 -453
- package/dist/spectral/BandsAndDos.svelte +90 -49
- package/dist/spectral/BrillouinBandsDos.svelte +151 -93
- package/dist/spectral/Dos.svelte +389 -258
- package/dist/spectral/helpers.js +55 -43
- package/dist/state.svelte.d.ts +1 -1
- package/dist/state.svelte.js +3 -2
- package/dist/structure/Arrow.svelte +59 -20
- package/dist/structure/AtomLegend.svelte +215 -134
- package/dist/structure/Bond.svelte +73 -47
- package/dist/structure/CanvasTooltip.svelte +10 -2
- package/dist/structure/CellSelect.svelte +72 -45
- package/dist/structure/Cylinder.svelte +33 -17
- package/dist/structure/Lattice.svelte +88 -33
- package/dist/structure/Structure.svelte +1063 -797
- package/dist/structure/Structure.svelte.d.ts +1 -1
- package/dist/structure/StructureControls.svelte +349 -118
- package/dist/structure/StructureExportPane.svelte +124 -89
- package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
- package/dist/structure/StructureInfoPane.svelte +304 -237
- package/dist/structure/StructureScene.svelte +879 -443
- package/dist/structure/StructureScene.svelte.d.ts +15 -7
- package/dist/structure/atom-properties.js +8 -8
- package/dist/structure/bonding.js +6 -7
- package/dist/structure/export.js +14 -29
- package/dist/structure/ferrox-wasm.js +1 -1
- package/dist/structure/index.d.ts +13 -3
- package/dist/structure/index.js +83 -23
- package/dist/structure/measure.d.ts +2 -2
- package/dist/structure/measure.js +4 -44
- package/dist/structure/parse.js +113 -141
- package/dist/structure/partial-occupancy.js +7 -10
- package/dist/structure/pbc.d.ts +1 -0
- package/dist/structure/pbc.js +16 -6
- package/dist/structure/supercell.d.ts +2 -2
- package/dist/structure/supercell.js +12 -22
- package/dist/structure/validation.js +1 -2
- package/dist/symmetry/SymmetryStats.svelte +84 -41
- package/dist/symmetry/WyckoffTable.svelte +26 -6
- package/dist/symmetry/cell-transform.js +5 -3
- package/dist/symmetry/index.js +8 -7
- package/dist/symmetry/spacegroups.js +148 -148
- package/dist/table/HeatmapTable.svelte +790 -554
- package/dist/table/HeatmapTable.svelte.d.ts +1 -1
- package/dist/table/ToggleMenu.svelte +125 -92
- package/dist/table/index.js +2 -4
- package/dist/theme/ThemeControl.svelte +21 -12
- package/dist/time.js +4 -1
- package/dist/tooltip/TooltipContent.svelte +33 -8
- package/dist/trajectory/Trajectory.svelte +758 -558
- package/dist/trajectory/TrajectoryError.svelte +14 -3
- package/dist/trajectory/TrajectoryExportPane.svelte +137 -83
- package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
- package/dist/trajectory/extract.js +10 -26
- package/dist/trajectory/format-detect.js +5 -5
- package/dist/trajectory/frame-reader.d.ts +1 -1
- package/dist/trajectory/frame-reader.js +5 -12
- package/dist/trajectory/helpers.d.ts +0 -1
- package/dist/trajectory/helpers.js +2 -17
- package/dist/trajectory/index.js +14 -12
- package/dist/trajectory/parse/ase.js +5 -4
- package/dist/trajectory/parse/hdf5.js +26 -18
- package/dist/trajectory/parse/index.js +13 -18
- package/dist/trajectory/parse/lammps.js +17 -7
- package/dist/trajectory/parse/vasp.js +5 -2
- package/dist/trajectory/parse/xyz.js +8 -7
- package/dist/trajectory/plotting.js +13 -8
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +13 -0
- package/dist/xrd/XrdPlot.svelte +337 -247
- package/dist/xrd/broadening.js +14 -9
- package/dist/xrd/calc-xrd.js +12 -18
- package/dist/xrd/parse.d.ts +1 -1
- package/dist/xrd/parse.js +17 -17
- package/package.json +99 -103
- package/readme.md +1 -1
- /package/dist/theme/{themes.js → themes.mjs} +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import type { D3InterpolateName } from '../colors';
|
|
1
2
|
import type { ElementSymbol } from '../element';
|
|
2
3
|
import type { IsosurfaceSettings, VolumetricData } from '../isosurface/types';
|
|
3
4
|
import type { Vec3 } from '../math';
|
|
4
|
-
import {
|
|
5
|
+
import type { CameraProjection, ShowBonds, VectorColorMode, VectorLayerConfig } from '../settings';
|
|
5
6
|
import type { AnyStructure, MeasureMode, Site } from './';
|
|
6
7
|
import { Lattice } from './';
|
|
7
8
|
import type { AtomColorConfig } from './atom-properties';
|
|
8
9
|
import type { MoyoDataset } from '@spglib/moyo-wasm';
|
|
9
10
|
import * as extras from '@threlte/extras';
|
|
10
|
-
import type
|
|
11
|
-
import { type Snippet } from 'svelte';
|
|
11
|
+
import { type ComponentProps, type Snippet } from 'svelte';
|
|
12
12
|
import { SvelteMap } from 'svelte/reactivity';
|
|
13
13
|
import { type Camera, type Scene } from 'three';
|
|
14
14
|
import type { BondingStrategy } from './bonding';
|
|
@@ -31,9 +31,17 @@ type $$ComponentProps = {
|
|
|
31
31
|
show_bonds?: ShowBonds;
|
|
32
32
|
show_site_labels?: boolean;
|
|
33
33
|
show_site_indices?: boolean;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
vector_configs?: Record<string, VectorLayerConfig>;
|
|
35
|
+
vector_scale?: number;
|
|
36
|
+
vector_color?: string;
|
|
37
|
+
vector_color_mode?: VectorColorMode;
|
|
38
|
+
vector_color_scale?: D3InterpolateName;
|
|
39
|
+
vector_normalize?: boolean;
|
|
40
|
+
vector_uniform_thickness?: boolean;
|
|
41
|
+
vector_origin_gap?: number;
|
|
42
|
+
vector_shaft_radius?: number;
|
|
43
|
+
vector_arrow_head_radius?: number;
|
|
44
|
+
vector_arrow_head_length?: number;
|
|
37
45
|
gizmo?: boolean | ComponentProps<typeof extras.Gizmo>;
|
|
38
46
|
hovered_idx?: number | null;
|
|
39
47
|
hovered_site?: Site | null;
|
|
@@ -91,6 +99,6 @@ type $$ComponentProps = {
|
|
|
91
99
|
volumetric_data?: VolumetricData;
|
|
92
100
|
isosurface_settings?: IsosurfaceSettings;
|
|
93
101
|
};
|
|
94
|
-
declare const StructureScene: import("svelte").Component<$$ComponentProps, {}, "cursor" | "site_label_offset" | "
|
|
102
|
+
declare const StructureScene: import("svelte").Component<$$ComponentProps, {}, "cursor" | "site_label_offset" | "vector_configs" | "camera" | "scene" | "orbit_controls" | "hidden_elements" | "hidden_prop_vals" | "element_radius_overrides" | "site_radius_overrides" | "selected_sites" | "hovered_idx" | "hovered_site" | "camera_is_moving" | "measured_sites" | "added_bonds" | "removed_bonds" | "active_sites" | "rotation_target_ref" | "initial_computed_zoom" | "add_atom_mode" | "add_element" | "dragging_atoms">;
|
|
95
103
|
type StructureScene = ReturnType<typeof StructureScene>;
|
|
96
104
|
export default StructureScene;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Utility functions for computing atom properties and applying color scales
|
|
2
2
|
import { calc_coordination_nums } from '../coordination';
|
|
3
3
|
import * as math from '../math';
|
|
4
|
+
import { wrap_to_unit_cell } from './pbc';
|
|
4
5
|
import { rgb } from 'd3-color';
|
|
5
6
|
import * as d3_sc from 'd3-scale-chromatic';
|
|
6
7
|
const GRAY = `#808080`;
|
|
@@ -15,7 +16,7 @@ const get_interpolator = (scale) => {
|
|
|
15
16
|
return interp_fn;
|
|
16
17
|
};
|
|
17
18
|
const to_hex = (interp_fn, t) => rgb(interp_fn(t)).formatHex();
|
|
18
|
-
const build_image_site = (site,
|
|
19
|
+
const build_image_site = (site, frac_to_cart, offset, orig_idx) => {
|
|
19
20
|
const img_abc = [
|
|
20
21
|
site.abc[0] + offset[0],
|
|
21
22
|
site.abc[1] + offset[1],
|
|
@@ -24,7 +25,7 @@ const build_image_site = (site, lattice_T, offset, orig_idx) => {
|
|
|
24
25
|
return {
|
|
25
26
|
...site,
|
|
26
27
|
abc: img_abc,
|
|
27
|
-
xyz:
|
|
28
|
+
xyz: frac_to_cart(img_abc),
|
|
28
29
|
properties: { ...site.properties, orig_site_idx: orig_idx },
|
|
29
30
|
};
|
|
30
31
|
};
|
|
@@ -85,23 +86,23 @@ function expand_structure_for_pbc(structure) {
|
|
|
85
86
|
return structure;
|
|
86
87
|
}
|
|
87
88
|
const { sites, lattice } = structure;
|
|
88
|
-
const
|
|
89
|
+
const frac_to_cart = math.create_frac_to_cart(lattice.matrix);
|
|
89
90
|
const pbc = lattice.pbc ?? [true, true, true];
|
|
90
91
|
const all_offsets = get_all_offsets(pbc);
|
|
91
92
|
// Small structures: expand all atoms
|
|
92
93
|
if (sites.length < 20 || !pbc.some((periodic) => periodic)) {
|
|
93
|
-
const image_sites = sites.flatMap((site, orig_idx) => all_offsets.map((offset) => build_image_site(site,
|
|
94
|
+
const image_sites = sites.flatMap((site, orig_idx) => all_offsets.map((offset) => build_image_site(site, frac_to_cart, offset, orig_idx)));
|
|
94
95
|
return { ...structure, sites: [...sites, ...image_sites] };
|
|
95
96
|
}
|
|
96
97
|
// Large structures: only expand atoms near boundaries (within 5Å bond distance)
|
|
97
98
|
const cutoff = [5.0 / lattice.a, 5.0 / lattice.b, 5.0 / lattice.c];
|
|
98
99
|
const image_sites = sites.flatMap((site, orig_idx) => {
|
|
99
|
-
const norm = site.abc
|
|
100
|
+
const norm = wrap_to_unit_cell(site.abc);
|
|
100
101
|
return all_offsets
|
|
101
102
|
.filter(([dx, dy, dz]) => (dx === 0 || (dx === -1 ? norm[0] <= cutoff[0] : norm[0] >= 1 - cutoff[0])) &&
|
|
102
103
|
(dy === 0 || (dy === -1 ? norm[1] <= cutoff[1] : norm[1] >= 1 - cutoff[1])) &&
|
|
103
104
|
(dz === 0 || (dz === -1 ? norm[2] <= cutoff[2] : norm[2] >= 1 - cutoff[2])))
|
|
104
|
-
.map((offset) => build_image_site(site,
|
|
105
|
+
.map((offset) => build_image_site(site, frac_to_cart, offset, orig_idx));
|
|
105
106
|
});
|
|
106
107
|
return { ...structure, sites: [...sites, ...image_sites] };
|
|
107
108
|
}
|
|
@@ -110,8 +111,7 @@ export function get_coordination_colors(structure, strategy = `electroneg_ratio`
|
|
|
110
111
|
// Check if structure has periodic boundary conditions
|
|
111
112
|
const has_lattice = `lattice` in structure && structure.lattice !== undefined;
|
|
112
113
|
const pbc = has_lattice ? structure.lattice.pbc : undefined;
|
|
113
|
-
const has_pbc = has_lattice &&
|
|
114
|
-
(pbc === undefined || pbc.some((is_periodic) => is_periodic));
|
|
114
|
+
const has_pbc = has_lattice && (pbc === undefined || pbc.some((is_periodic) => is_periodic));
|
|
115
115
|
// For PBC structures, expand with images from neighboring cells for accurate coordination
|
|
116
116
|
const coord_structure = has_pbc ? expand_structure_for_pbc(structure) : structure;
|
|
117
117
|
// Calculate coordination numbers on the (potentially expanded) structure
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
import { element_data } from '../element';
|
|
3
3
|
import * as math from '../math';
|
|
4
4
|
const element_lookup = new Map(element_data.map((el) => [el.symbol, el]));
|
|
5
|
-
const covalent_radii = new Map(element_data
|
|
5
|
+
const covalent_radii = new Map(element_data
|
|
6
|
+
.filter((el) => el.covalent_radius !== null)
|
|
7
|
+
.map((el) => [el.symbol, el.covalent_radius]));
|
|
6
8
|
// Get the species with highest occupancy from a site.
|
|
7
9
|
const get_majority_species = (site) => (site.species ?? []).reduce((max_species, species) => (species.occu > max_species.occu ? species : max_species), site.species?.[0] ?? { element: ``, occu: -1 });
|
|
8
10
|
// Helper to extract numeric index from site properties
|
|
@@ -67,6 +69,7 @@ export function compute_bond_transform(pos_1, pos_2) {
|
|
|
67
69
|
(pos_1[2] + pos_2[2]) / 2,
|
|
68
70
|
];
|
|
69
71
|
return new Float32Array([
|
|
72
|
+
// Return flattened column-major 4x4 matrix for Three.js
|
|
70
73
|
...[m00, m10, m20, 0],
|
|
71
74
|
...[m01 * height, m11 * height, m21 * height, 0],
|
|
72
75
|
...[m02, m12, m22, 0],
|
|
@@ -263,17 +266,13 @@ export function solid_angle(structure, { min_solid_angle = 0.01, min_face_area =
|
|
|
263
266
|
for (let idx_a = 0; idx_a < sites.length - 1; idx_a++) {
|
|
264
267
|
const [x1, y1, z1] = sites[idx_a].xyz;
|
|
265
268
|
const majority_a = get_majority_species(sites[idx_a]);
|
|
266
|
-
const radius_a = majority_a.element
|
|
267
|
-
? covalent_radii.get(majority_a.element)
|
|
268
|
-
: undefined;
|
|
269
|
+
const radius_a = majority_a.element ? covalent_radii.get(majority_a.element) : undefined;
|
|
269
270
|
for (const idx_b of get_candidates(sites[idx_a].xyz, sites, spatial)) {
|
|
270
271
|
if (idx_b <= idx_a)
|
|
271
272
|
continue;
|
|
272
273
|
const [x2, y2, z2] = sites[idx_b].xyz;
|
|
273
274
|
const majority_b = get_majority_species(sites[idx_b]);
|
|
274
|
-
const radius_b = majority_b.element
|
|
275
|
-
? covalent_radii.get(majority_b.element)
|
|
276
|
-
: undefined;
|
|
275
|
+
const radius_b = majority_b.element ? covalent_radii.get(majority_b.element) : undefined;
|
|
277
276
|
const [dx, dy, dz] = [x2 - x1, y2 - y1, z2 - z1];
|
|
278
277
|
const dist_sq = dx * dx + dy * dy + dz * dz;
|
|
279
278
|
const dist = Math.sqrt(dist_sq);
|
package/dist/structure/export.js
CHANGED
|
@@ -17,9 +17,9 @@ export function has_color_property(mat) {
|
|
|
17
17
|
const red_channel = color_obj.r;
|
|
18
18
|
const green_channel = color_obj.g;
|
|
19
19
|
const blue_channel = color_obj.b;
|
|
20
|
-
return typeof red_channel === `number` &&
|
|
20
|
+
return (typeof red_channel === `number` &&
|
|
21
21
|
typeof green_channel === `number` &&
|
|
22
|
-
typeof blue_channel === `number
|
|
22
|
+
typeof blue_channel === `number`);
|
|
23
23
|
}
|
|
24
24
|
// Extract color from a ShaderMaterial by checking common color uniform patterns
|
|
25
25
|
function extract_shader_color(shader_mat) {
|
|
@@ -129,9 +129,7 @@ export function generate_mtl_content(scene) {
|
|
|
129
129
|
lines.push(`Ks 0.500000 0.500000 0.500000`);
|
|
130
130
|
lines.push(`Ns 96.078431`); // Specular exponent
|
|
131
131
|
// Transparency (d = 1.0 is fully opaque)
|
|
132
|
-
const opacity = `opacity` in mat && typeof mat.opacity === `number`
|
|
133
|
-
? mat.opacity
|
|
134
|
-
: 1.0;
|
|
132
|
+
const opacity = `opacity` in mat && typeof mat.opacity === `number` ? mat.opacity : 1.0;
|
|
135
133
|
lines.push(`d ${opacity.toFixed(6)}`);
|
|
136
134
|
// Illumination model (2 = highlight on)
|
|
137
135
|
lines.push(`illum 2`);
|
|
@@ -151,7 +149,7 @@ function extract_material_color(mat) {
|
|
|
151
149
|
// This is necessary because GLB/OBJ exporters don't handle InstancedMesh properly
|
|
152
150
|
// Note: Threlte's InstancedMesh sets isInstancedMesh=true but type remains "Mesh"
|
|
153
151
|
// Type guard for InstancedMesh (Three.js uses isInstancedMesh property, not exposed in Object3D type)
|
|
154
|
-
const is_instanced_mesh = (obj) => obj.isInstancedMesh
|
|
152
|
+
const is_instanced_mesh = (obj) => obj.isInstancedMesh || obj.type === `InstancedMesh`;
|
|
155
153
|
function convert_instanced_meshes_to_regular(scene) {
|
|
156
154
|
// STEP 1: Collect material colors from ORIGINAL scene BEFORE cloning
|
|
157
155
|
// This is crucial because scene.clone() may not properly preserve Threlte's material colors
|
|
@@ -357,16 +355,14 @@ export function structure_to_xyz_str(structure) {
|
|
|
357
355
|
if (formula && formula !== `Unknown`)
|
|
358
356
|
comment_parts.push(formula);
|
|
359
357
|
// Include extended XYZ lattice information when available so round-trips preserve lattice
|
|
360
|
-
if (
|
|
358
|
+
if (`lattice` in structure && structure.lattice?.matrix?.length === 3) {
|
|
361
359
|
const lattice_values = structure.lattice.matrix
|
|
362
360
|
.flat()
|
|
363
361
|
.map((value) => (Number.isFinite(value) ? value : 0).toFixed(8))
|
|
364
362
|
.join(` `);
|
|
365
363
|
comment_parts.push(`Lattice="${lattice_values}"`);
|
|
366
364
|
}
|
|
367
|
-
const comment = comment_parts.length > 0
|
|
368
|
-
? comment_parts.join(` `)
|
|
369
|
-
: `Generated from structure`;
|
|
365
|
+
const comment = comment_parts.length > 0 ? comment_parts.join(` `) : `Generated from structure`;
|
|
370
366
|
lines.push(comment);
|
|
371
367
|
// Cache converter for fractional→Cartesian (if lattice available)
|
|
372
368
|
const frac_to_cart = `lattice` in structure && structure.lattice?.matrix?.length === 3
|
|
@@ -376,9 +372,7 @@ export function structure_to_xyz_str(structure) {
|
|
|
376
372
|
for (const site of structure.sites) {
|
|
377
373
|
// Extract element symbol from species
|
|
378
374
|
let element_symbol = `X`; // default fallback
|
|
379
|
-
if (site.species &&
|
|
380
|
-
Array.isArray(site.species) &&
|
|
381
|
-
site.species.length > 0) {
|
|
375
|
+
if (site.species && Array.isArray(site.species) && site.species.length > 0) {
|
|
382
376
|
// species is an array of Species objects with element property
|
|
383
377
|
const first_species = site.species[0];
|
|
384
378
|
if (first_species && `element` in first_species && first_species.element)
|
|
@@ -469,7 +463,8 @@ export function structure_to_cif_str(structure) {
|
|
|
469
463
|
lines.push(`_cell_angle_gamma ${lattice.gamma.toFixed(6)}`);
|
|
470
464
|
}
|
|
471
465
|
// Space group information
|
|
472
|
-
if (`symmetry` in structure &&
|
|
466
|
+
if (`symmetry` in structure &&
|
|
467
|
+
structure.symmetry &&
|
|
473
468
|
typeof structure.symmetry === `object`) {
|
|
474
469
|
const symmetry = structure.symmetry;
|
|
475
470
|
if (`space_group_symbol` in symmetry && symmetry.space_group_symbol) {
|
|
@@ -489,9 +484,7 @@ export function structure_to_cif_str(structure) {
|
|
|
489
484
|
lines.push(`_atom_site_fract_z`);
|
|
490
485
|
lines.push(`_atom_site_occupancy`);
|
|
491
486
|
// Cache inverse transpose for Cartesian→fractional conversion (avoids recomputing per site)
|
|
492
|
-
const cart_to_frac = lattice.matrix?.length === 3
|
|
493
|
-
? math.create_cart_to_frac(lattice.matrix)
|
|
494
|
-
: null;
|
|
487
|
+
const cart_to_frac = lattice.matrix?.length === 3 ? math.create_cart_to_frac(lattice.matrix) : null;
|
|
495
488
|
// Atom sites
|
|
496
489
|
for (let idx = 0; idx < structure.sites.length; idx++) {
|
|
497
490
|
const site = structure.sites[idx];
|
|
@@ -500,9 +493,7 @@ export function structure_to_cif_str(structure) {
|
|
|
500
493
|
// Extract element symbol from species
|
|
501
494
|
let element_symbol = `X`; // default fallback
|
|
502
495
|
let occupancy = 1;
|
|
503
|
-
if (site.species &&
|
|
504
|
-
Array.isArray(site.species) &&
|
|
505
|
-
site.species.length > 0) {
|
|
496
|
+
if (site.species && Array.isArray(site.species) && site.species.length > 0) {
|
|
506
497
|
const first_species = site.species[0];
|
|
507
498
|
if (first_species && `element` in first_species && first_species.element) {
|
|
508
499
|
element_symbol = first_species.element;
|
|
@@ -556,9 +547,7 @@ export function structure_to_poscar_str(structure) {
|
|
|
556
547
|
const element_symbols = [];
|
|
557
548
|
for (const site of structure.sites) {
|
|
558
549
|
let element_symbol = `X`; // default fallback
|
|
559
|
-
if (site.species &&
|
|
560
|
-
Array.isArray(site.species) &&
|
|
561
|
-
site.species.length > 0) {
|
|
550
|
+
if (site.species && Array.isArray(site.species) && site.species.length > 0) {
|
|
562
551
|
const first_species = site.species[0];
|
|
563
552
|
if (first_species && `element` in first_species && first_species.element) {
|
|
564
553
|
element_symbol = first_species.element;
|
|
@@ -582,16 +571,12 @@ export function structure_to_poscar_str(structure) {
|
|
|
582
571
|
// Coordinate mode (Direct = fractional coordinates)
|
|
583
572
|
lines.push(`Direct`);
|
|
584
573
|
// Cache inverse transpose for Cartesian→fractional conversion (avoids recomputing per site)
|
|
585
|
-
const cart_to_frac = lattice.matrix?.length === 3
|
|
586
|
-
? math.create_cart_to_frac(lattice.matrix)
|
|
587
|
-
: null;
|
|
574
|
+
const cart_to_frac = lattice.matrix?.length === 3 ? math.create_cart_to_frac(lattice.matrix) : null;
|
|
588
575
|
// Atom coordinates grouped by element
|
|
589
576
|
for (const element_symbol of element_symbols) {
|
|
590
577
|
for (const site of structure.sites) {
|
|
591
578
|
let site_element = `X`;
|
|
592
|
-
if (site.species &&
|
|
593
|
-
Array.isArray(site.species) &&
|
|
594
|
-
site.species.length > 0) {
|
|
579
|
+
if (site.species && Array.isArray(site.species) && site.species.length > 0) {
|
|
595
580
|
const first_species = site.species[0];
|
|
596
581
|
if (first_species && `element` in first_species && first_species.element) {
|
|
597
582
|
site_element = first_species.element;
|
|
@@ -33,7 +33,7 @@ export function ensure_ferrox_wasm_ready() {
|
|
|
33
33
|
catch (err) {
|
|
34
34
|
// Clear the promise on failure so retry is possible
|
|
35
35
|
init_promise = null;
|
|
36
|
-
throw new Error(`Failed to load matterviz-wasm. Install with:
|
|
36
|
+
throw new Error(`Failed to load matterviz-wasm. Install with: npm add matterviz-wasm. Original error: ${err}`, { cause: err });
|
|
37
37
|
}
|
|
38
38
|
})();
|
|
39
39
|
}
|
|
@@ -67,11 +67,21 @@ export declare function format_formula_by_electronegativity(structure: AnyStruct
|
|
|
67
67
|
export declare const atomic_radii: CompositionType;
|
|
68
68
|
export declare function get_density(structure: Crystal): number;
|
|
69
69
|
export declare function get_center_of_mass(structure: AnyStructure): Vec3;
|
|
70
|
-
export declare
|
|
70
|
+
export declare const VECTOR_KEY_PREFIXES: readonly ["force", "forces", "magmom", "magmoms", "spin", "spins"];
|
|
71
|
+
export declare function is_vector_key(key: string): boolean;
|
|
72
|
+
export declare const VECTOR_PALETTE: readonly ["#e74c3c", "#3498db", "#2ecc71", "#f39c12", "#9b59b6", "#1abc9c"];
|
|
73
|
+
export declare const default_vector_configs: (keys: string[]) => {
|
|
74
|
+
[k: string]: {
|
|
75
|
+
visible: boolean;
|
|
76
|
+
color: "#e74c3c" | "#3498db" | "#2ecc71" | "#f39c12" | "#9b59b6" | "#1abc9c" | null;
|
|
77
|
+
scale: null;
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
export declare function get_all_site_vectors(site: Site): {
|
|
71
81
|
vec: Vec3;
|
|
72
82
|
key: string;
|
|
73
|
-
}
|
|
74
|
-
export declare function
|
|
83
|
+
}[];
|
|
84
|
+
export declare function get_structure_vector_keys(structure: AnyStructure): string[];
|
|
75
85
|
export interface StructureHandlerData {
|
|
76
86
|
structure?: AnyStructure;
|
|
77
87
|
filename?: string;
|
package/dist/structure/index.js
CHANGED
|
@@ -42,16 +42,14 @@ export function format_chemical_formula(structure, sort_fn) {
|
|
|
42
42
|
}
|
|
43
43
|
export function format_formula_by_electronegativity(structure) {
|
|
44
44
|
// concatenate elements in a structure followed by their amount sorted by electronegativity
|
|
45
|
-
return format_chemical_formula(structure, (symbols) =>
|
|
46
|
-
const elec_neg1 = element_data.find((el) => el.symbol === el1)?.electronegativity ??
|
|
47
|
-
|
|
48
|
-
const elec_neg2 = element_data.find((el) => el.symbol === el2)?.electronegativity ??
|
|
49
|
-
0;
|
|
45
|
+
return format_chemical_formula(structure, (symbols) => symbols.sort((el1, el2) => {
|
|
46
|
+
const elec_neg1 = element_data.find((el) => el.symbol === el1)?.electronegativity ?? 0;
|
|
47
|
+
const elec_neg2 = element_data.find((el) => el.symbol === el2)?.electronegativity ?? 0;
|
|
50
48
|
// Sort by electronegativity (ascending), then alphabetically for ties
|
|
51
49
|
if (elec_neg1 !== elec_neg2)
|
|
52
50
|
return elec_neg1 - elec_neg2;
|
|
53
51
|
return el1.localeCompare(el2);
|
|
54
|
-
}))
|
|
52
|
+
}));
|
|
55
53
|
}
|
|
56
54
|
// Atomic radii in Angstroms (used for relative sizing, not absolute rendering scale)
|
|
57
55
|
export const atomic_radii = Object.fromEntries(element_data.map((el) => [el.symbol, el.atomic_radius ?? 1]));
|
|
@@ -84,25 +82,87 @@ export function get_center_of_mass(structure) {
|
|
|
84
82
|
}
|
|
85
83
|
return math.scale(center, 1 / total_weight);
|
|
86
84
|
}
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
85
|
+
// Recognized prefixes for per-site vector data (force, magnetic moment, spin).
|
|
86
|
+
// Both singular and plural forms are accepted. Keys matching exactly or starting
|
|
87
|
+
// with one of these followed by `_` (e.g. `force_DFT`) are treated as vectors.
|
|
88
|
+
export const VECTOR_KEY_PREFIXES = [
|
|
89
|
+
`force`,
|
|
90
|
+
`forces`,
|
|
91
|
+
`magmom`,
|
|
92
|
+
`magmoms`,
|
|
93
|
+
`spin`,
|
|
94
|
+
`spins`,
|
|
95
|
+
];
|
|
96
|
+
export function is_vector_key(key) {
|
|
97
|
+
return VECTOR_KEY_PREFIXES.some((prefix) => key === prefix || key.startsWith(`${prefix}_`));
|
|
98
|
+
}
|
|
99
|
+
// Default color palette for distinguishing multiple vector layers
|
|
100
|
+
export const VECTOR_PALETTE = [
|
|
101
|
+
`#e74c3c`,
|
|
102
|
+
`#3498db`,
|
|
103
|
+
`#2ecc71`,
|
|
104
|
+
`#f39c12`,
|
|
105
|
+
`#9b59b6`,
|
|
106
|
+
`#1abc9c`,
|
|
107
|
+
];
|
|
108
|
+
// Single key → null color (semantic coloring); multiple keys → palette colors.
|
|
109
|
+
export const default_vector_configs = (keys) => Object.fromEntries(keys.map((key, idx) => [
|
|
110
|
+
key,
|
|
111
|
+
{
|
|
112
|
+
visible: true,
|
|
113
|
+
color: keys.length > 1 ? VECTOR_PALETTE[idx % VECTOR_PALETTE.length] : null,
|
|
114
|
+
scale: null,
|
|
115
|
+
},
|
|
116
|
+
]));
|
|
117
|
+
function try_parse_vec3(val) {
|
|
118
|
+
if (Array.isArray(val) &&
|
|
119
|
+
val.length === 3 &&
|
|
120
|
+
val.every((elem) => typeof elem === `number` && isFinite(elem)))
|
|
121
|
+
return val;
|
|
122
|
+
if (typeof val === `number` && isFinite(val))
|
|
123
|
+
return [0, 0, val];
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
// Priority index for ordering: bare names first in VECTOR_KEY_PREFIXES order,
|
|
127
|
+
// then prefixed keys in the same prefix order, alphabetically within each prefix group.
|
|
128
|
+
function vector_key_sort_order(key) {
|
|
129
|
+
for (const [prefix_idx, prefix] of VECTOR_KEY_PREFIXES.entries()) {
|
|
130
|
+
if (key === prefix)
|
|
131
|
+
return [prefix_idx, 0, ``];
|
|
132
|
+
if (key.startsWith(`${prefix}_`))
|
|
133
|
+
return [prefix_idx, 1, key];
|
|
134
|
+
}
|
|
135
|
+
return [VECTOR_KEY_PREFIXES.length, 0, key];
|
|
136
|
+
}
|
|
137
|
+
function compare_vector_keys(left, right) {
|
|
138
|
+
const ord_l = vector_key_sort_order(left);
|
|
139
|
+
const ord_r = vector_key_sort_order(right);
|
|
140
|
+
return ord_l[0] - ord_r[0] || ord_l[1] - ord_r[1] || ord_l[2].localeCompare(ord_r[2]);
|
|
141
|
+
}
|
|
142
|
+
// Extract ALL vector properties from a site (not just the first match).
|
|
143
|
+
// Returns entries for every key that is_vector_key() and has a valid 3D vector value.
|
|
144
|
+
// Ordered by VECTOR_KEY_PREFIXES priority, then alphabetically for prefixed keys.
|
|
145
|
+
export function get_all_site_vectors(site) {
|
|
92
146
|
const props = site.properties;
|
|
93
147
|
if (!props)
|
|
94
|
-
return
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (
|
|
101
|
-
|
|
148
|
+
return [];
|
|
149
|
+
const results = [];
|
|
150
|
+
for (const key of Object.keys(props)) {
|
|
151
|
+
if (!is_vector_key(key))
|
|
152
|
+
continue;
|
|
153
|
+
const vec = try_parse_vec3(props[key]);
|
|
154
|
+
if (vec)
|
|
155
|
+
results.push({ vec, key });
|
|
102
156
|
}
|
|
103
|
-
return
|
|
157
|
+
return results.sort((left, right) => compare_vector_keys(left.key, right.key));
|
|
104
158
|
}
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
|
|
159
|
+
// Collect the union of all vector property keys across all sites in a structure,
|
|
160
|
+
// preserving VECTOR_KEY_PREFIXES priority order.
|
|
161
|
+
export function get_structure_vector_keys(structure) {
|
|
162
|
+
const seen = new Set();
|
|
163
|
+
for (const site of structure.sites) {
|
|
164
|
+
for (const { key } of get_all_site_vectors(site))
|
|
165
|
+
seen.add(key);
|
|
166
|
+
}
|
|
167
|
+
return [...seen].sort(compare_vector_keys);
|
|
108
168
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Matrix3x3, Vec3 } from '../math';
|
|
1
|
+
import type { LatticeConverters, Matrix3x3, Vec3 } from '../math';
|
|
2
2
|
export type AngleMode = `degrees` | `radians`;
|
|
3
3
|
export declare const MAX_SELECTED_SITES = 8;
|
|
4
|
-
export declare function displacement_pbc(from: Vec3, to: Vec3, lattice_matrix: Matrix3x3 | null | undefined,
|
|
4
|
+
export declare function displacement_pbc(from: Vec3, to: Vec3, lattice_matrix: Matrix3x3 | null | undefined, converters?: LatticeConverters): Vec3;
|
|
5
5
|
export declare function distance_pbc(a: Vec3, b: Vec3, lattice_matrix: Matrix3x3): number;
|
|
6
6
|
export declare function angle_between_vectors(v1: Vec3, v2: Vec3, mode?: AngleMode): number;
|
|
@@ -1,55 +1,15 @@
|
|
|
1
1
|
// functions for measuring distances and angles between structure sites
|
|
2
|
-
import {
|
|
2
|
+
import { min_image_displacement, subtract } from '../math';
|
|
3
3
|
export const MAX_SELECTED_SITES = 8;
|
|
4
4
|
// Calculate minimum image displacement between two points under PBC
|
|
5
5
|
// If lattice_matrix is null/undefined, returns Euclidean displacement
|
|
6
|
-
export function displacement_pbc(from, to, lattice_matrix,
|
|
7
|
-
// For non-periodic structures, return direct displacement
|
|
6
|
+
export function displacement_pbc(from, to, lattice_matrix, converters) {
|
|
8
7
|
if (!lattice_matrix)
|
|
9
8
|
return subtract(to, from);
|
|
10
|
-
|
|
11
|
-
const frac_from = mat3x3_vec3_multiply(inv_mat, from);
|
|
12
|
-
const frac_to = mat3x3_vec3_multiply(inv_mat, to);
|
|
13
|
-
// Wrap fractional coordinates to [0,1) for easier boundary checking
|
|
14
|
-
const frac_from_wrapped = [
|
|
15
|
-
frac_from[0] - Math.floor(frac_from[0]),
|
|
16
|
-
frac_from[1] - Math.floor(frac_from[1]),
|
|
17
|
-
frac_from[2] - Math.floor(frac_from[2]),
|
|
18
|
-
];
|
|
19
|
-
const frac_to_wrapped = [
|
|
20
|
-
frac_to[0] - Math.floor(frac_to[0]),
|
|
21
|
-
frac_to[1] - Math.floor(frac_to[1]),
|
|
22
|
-
frac_to[2] - Math.floor(frac_to[2]),
|
|
23
|
-
];
|
|
24
|
-
// Find minimum image by testing all nearby lattice translations
|
|
25
|
-
let min_dist_sq = Infinity;
|
|
26
|
-
let best_displacement = [0, 0, 0];
|
|
27
|
-
// Test lattice images in a 3x3x3 neighborhood (sufficient for minimum image)
|
|
28
|
-
for (let ii = -1; ii <= 1; ii++) {
|
|
29
|
-
for (let jj = -1; jj <= 1; jj++) {
|
|
30
|
-
for (let kk = -1; kk <= 1; kk++) {
|
|
31
|
-
// Fractional displacement with lattice translation
|
|
32
|
-
const frac_diff = [
|
|
33
|
-
frac_to_wrapped[0] - frac_from_wrapped[0] + ii,
|
|
34
|
-
frac_to_wrapped[1] - frac_from_wrapped[1] + jj,
|
|
35
|
-
frac_to_wrapped[2] - frac_from_wrapped[2] + kk,
|
|
36
|
-
];
|
|
37
|
-
// Convert to cartesian
|
|
38
|
-
const cart_diff = mat3x3_vec3_multiply(lattice_matrix, frac_diff);
|
|
39
|
-
const dist_sq = cart_diff[0] ** 2 + cart_diff[1] ** 2 + cart_diff[2] ** 2;
|
|
40
|
-
// Keep the shortest displacement
|
|
41
|
-
if (dist_sq < min_dist_sq) {
|
|
42
|
-
min_dist_sq = dist_sq;
|
|
43
|
-
best_displacement = cart_diff;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return best_displacement;
|
|
9
|
+
return min_image_displacement(from, to, lattice_matrix, converters);
|
|
49
10
|
}
|
|
50
11
|
export function distance_pbc(a, b, lattice_matrix) {
|
|
51
|
-
const
|
|
52
|
-
const [dx, dy, dz] = displacement_pbc(a, b, lattice_matrix, inv_mat);
|
|
12
|
+
const [dx, dy, dz] = displacement_pbc(a, b, lattice_matrix);
|
|
53
13
|
return Math.hypot(dx, dy, dz);
|
|
54
14
|
}
|
|
55
15
|
export function angle_between_vectors(v1, v2, mode = `degrees`) {
|