@ccp-nc/crystvis-js 0.7.0 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/lib/render.js +41 -15
  2. package/package.json +3 -2
  3. package/test/render.js +168 -0
  4. package/test/setup-dom.cjs +65 -3
  5. package/docs/data/search.json +0 -1
  6. package/docs/fonts/Inconsolata-Regular.ttf +0 -0
  7. package/docs/fonts/OpenSans-Regular.ttf +0 -0
  8. package/docs/fonts/WorkSans-Bold.ttf +0 -0
  9. package/docs/index.html +0 -59
  10. package/docs/lib_model.module_js-AtomImage.html +0 -3
  11. package/docs/lib_model.module_js-BondImage.html +0 -3
  12. package/docs/lib_model.module_js-Model.html +0 -3
  13. package/docs/lib_model.module_js.html +0 -3
  14. package/docs/lib_modelview.module_js-ModelView.html +0 -12
  15. package/docs/lib_modelview.module_js.html +0 -3
  16. package/docs/lib_visualizer.module_js-CrystVis.html +0 -3
  17. package/docs/lib_visualizer.module_js.html +0 -3
  18. package/docs/model.js.html +0 -2191
  19. package/docs/modelview.js.html +0 -473
  20. package/docs/scripts/core.js +0 -726
  21. package/docs/scripts/core.min.js +0 -23
  22. package/docs/scripts/resize.js +0 -90
  23. package/docs/scripts/search.js +0 -265
  24. package/docs/scripts/search.min.js +0 -6
  25. package/docs/scripts/third-party/Apache-License-2.0.txt +0 -202
  26. package/docs/scripts/third-party/fuse.js +0 -9
  27. package/docs/scripts/third-party/hljs-line-num-original.js +0 -369
  28. package/docs/scripts/third-party/hljs-line-num.js +0 -1
  29. package/docs/scripts/third-party/hljs-original.js +0 -5171
  30. package/docs/scripts/third-party/hljs.js +0 -1
  31. package/docs/scripts/third-party/popper.js +0 -5
  32. package/docs/scripts/third-party/tippy.js +0 -1
  33. package/docs/scripts/third-party/tocbot.js +0 -672
  34. package/docs/scripts/third-party/tocbot.min.js +0 -1
  35. package/docs/styles/clean-jsdoc-theme-base.css +0 -1159
  36. package/docs/styles/clean-jsdoc-theme-dark.css +0 -412
  37. package/docs/styles/clean-jsdoc-theme-light.css +0 -482
  38. package/docs/styles/clean-jsdoc-theme-scrollbar.css +0 -30
  39. package/docs/styles/clean-jsdoc-theme-without-scrollbar.min.css +0 -1
  40. package/docs/styles/clean-jsdoc-theme.min.css +0 -1
  41. package/docs/tutorial-Events.html +0 -13
  42. package/docs/tutorial-Queries.html +0 -16
  43. package/docs/tutorial-ThreejsMigration.html +0 -25
  44. package/docs/visualizer.js.html +0 -810
package/lib/render.js CHANGED
@@ -27,6 +27,7 @@ import {
27
27
 
28
28
  // Ratio of secondary directional light intensity to primary
29
29
  const SECONDARY_LIGHT_INTENSITY_RATIO = 0.4;
30
+ const DRAG_THRESHOLD_SQ = 25;
30
31
 
31
32
  // themes:
32
33
  const themes = {
@@ -116,8 +117,34 @@ class Renderer {
116
117
 
117
118
  // Raycast for clicks
118
119
  this._rcastlist = [];
119
- this._boundRaycastClick = this._raycastClick.bind(this);
120
- this._r.domElement.addEventListener('pointerdown', this._boundRaycastClick);
120
+ this._raycaster = new THREE.Raycaster();
121
+ this._ndcVector = new THREE.Vector2();
122
+ this._clickDownX = 0;
123
+ this._clickDownY = 0;
124
+ this._pointerDownValid = false;
125
+ this._boundClickDown = (e) => {
126
+ if (!e.isPrimary) return;
127
+ this._clickDownX = e.clientX;
128
+ this._clickDownY = e.clientY;
129
+ this._pointerDownValid = true;
130
+ };
131
+ this._boundClickUp = (e) => {
132
+ if (!e.isPrimary) return;
133
+ if (!this._pointerDownValid) return;
134
+ this._pointerDownValid = false;
135
+ const dx = e.clientX - this._clickDownX;
136
+ const dy = e.clientY - this._clickDownY;
137
+ if (dx * dx + dy * dy <= DRAG_THRESHOLD_SQ) {
138
+ this._raycastClick(e);
139
+ }
140
+ };
141
+ this._boundClickCancel = (e) => {
142
+ if (!e.isPrimary) return;
143
+ this._pointerDownValid = false;
144
+ };
145
+ this._r.domElement.addEventListener('pointerdown', this._boundClickDown);
146
+ this._r.domElement.addEventListener('pointerup', this._boundClickUp);
147
+ this._r.domElement.addEventListener('pointercancel', this._boundClickCancel);
121
148
 
122
149
  // Groups
123
150
  this._groups = {
@@ -170,7 +197,6 @@ class Renderer {
170
197
  _updateSize() {
171
198
  this._w = this._w || this._div.innerWidth();
172
199
  this._h = this._h || this._div.innerHeight();
173
- this._offset = this._div.offset();
174
200
  }
175
201
 
176
202
  _resize() {
@@ -191,11 +217,10 @@ class Renderer {
191
217
  // We create a 2D vector
192
218
  var vector = this.documentToWorld(e.clientX, e.clientY);
193
219
 
194
- // We create a raycaster, which is some kind of laser going through your scene
195
- var raycaster = new THREE.Raycaster();
220
+ // Reuse the shared raycaster instance
196
221
  // We apply two parameters to the 'laser', its origin (where the user clicked)
197
222
  // and the direction (what the camera 'sees')
198
- raycaster.setFromCamera(vector, this._c);
223
+ this._raycaster.setFromCamera(vector, this._c);
199
224
 
200
225
  // We get all the objects the 'laser' find on its way (it returns an array containing the objects)
201
226
  for (var i = 0; i < this._rcastlist.length; ++i) {
@@ -205,7 +230,7 @@ class Renderer {
205
230
  var filter = this._rcastlist[i][2];
206
231
 
207
232
  targ = targ || this._s;
208
- var intersects = raycaster.intersectObjects(targ.children);
233
+ var intersects = this._raycaster.intersectObjects(targ.children);
209
234
 
210
235
  var objects = [];
211
236
  for (var j = 0; j < intersects.length; ++j) {
@@ -349,8 +374,10 @@ class Renderer {
349
374
  this._animFrameId = null;
350
375
  }
351
376
 
352
- // 2. Remove the raycaster's own pointerdown listener
353
- this._r.domElement.removeEventListener('pointerdown', this._boundRaycastClick);
377
+ // 2. Remove the raycaster's own pointer listeners
378
+ this._r.domElement.removeEventListener('pointerdown', this._boundClickDown);
379
+ this._r.domElement.removeEventListener('pointerup', this._boundClickUp);
380
+ this._r.domElement.removeEventListener('pointercancel', this._boundClickCancel);
354
381
  this._rcastlist = [];
355
382
  this._sboxlist = [];
356
383
 
@@ -525,15 +552,14 @@ class Renderer {
525
552
  * Convert coordinates in the dom element frame to coordinates in the world frame
526
553
  */
527
554
  documentToWorld(x, y) {
528
- // We create a 2D vector
529
- var vector = new THREE.Vector2();
555
+ const rect = this._r.domElement.getBoundingClientRect();
530
556
  // We set its position where the user clicked and we convert it to a number between -1 & 1
531
- vector.set(
532
- 2 * ((x - this._offset.left) / this._w) - 1,
533
- 1 - 2 * ((y - this._offset.top) / this._h)
557
+ this._ndcVector.set(
558
+ 2 * ((x - rect.left) / rect.width) - 1,
559
+ 1 - 2 * ((y - rect.top) / rect.height)
534
560
  );
535
561
 
536
- return vector;
562
+ return this._ndcVector;
537
563
  }
538
564
 
539
565
  // Style
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ccp-nc/crystvis-js",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "A Three.js based crystallographic visualisation tool",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -69,7 +69,7 @@
69
69
  },
70
70
  "homepage": "https://github.com/ccp-nc/crystvis-js#readme",
71
71
  "dependencies": {
72
- "@ccp-nc/crystcif-parse": "^0.2.9",
72
+ "@ccp-nc/crystcif-parse": "^0.3.0",
73
73
  "@jkshenton/three-bmfont-text": "^4.0.1",
74
74
  "buffer": "^6.0.3",
75
75
  "chroma-js": "^3.2.0",
@@ -78,6 +78,7 @@
78
78
  "load-bmfont": "^1.4.2",
79
79
  "lodash": "^4.17.23",
80
80
  "mathjs": "^14.9.1",
81
+ "mendeleev": "^1.2.2",
81
82
  "three": "^0.178.0",
82
83
  "yargs-parser": "^22.0.0"
83
84
  },
package/test/render.js ADDED
@@ -0,0 +1,168 @@
1
+ 'use strict';
2
+
3
+ import * as chai from 'chai';
4
+ import { Renderer } from '../lib/render.js';
5
+
6
+ const expect = chai.expect;
7
+
8
+ function dispatchPointerEvent(target, type, x, y, { isPrimary = true } = {}) {
9
+ const event = new window.MouseEvent(type, {
10
+ bubbles: true,
11
+ clientX: x,
12
+ clientY: y,
13
+ });
14
+ Object.defineProperty(event, 'isPrimary', { value: isPrimary });
15
+ target.dispatchEvent(event);
16
+ }
17
+
18
+ describe('Renderer click drag guard', function () {
19
+ let renderer;
20
+ let originalAnimate;
21
+
22
+ before(function () {
23
+ originalAnimate = Renderer.prototype._animate;
24
+ Renderer.prototype._animate = function () {};
25
+ });
26
+
27
+ after(function () {
28
+ Renderer.prototype._animate = originalAnimate;
29
+ });
30
+
31
+ beforeEach(function () {
32
+ const host = document.getElementById('crystvis');
33
+ host.innerHTML = '';
34
+ renderer = new Renderer('#crystvis', 320, 240);
35
+ renderer._r.dispose = () => {};
36
+ });
37
+
38
+ afterEach(function () {
39
+ if (renderer && renderer._r) {
40
+ renderer.dispose();
41
+ }
42
+ renderer = null;
43
+ const host = document.getElementById('crystvis');
44
+ host.innerHTML = '';
45
+ });
46
+
47
+ it('should raycast on pointerup when the pointer stays within the drag threshold', function () {
48
+ let raycastCalls = 0;
49
+ renderer._raycastClick = () => {
50
+ raycastCalls++;
51
+ };
52
+
53
+ dispatchPointerEvent(renderer._r.domElement, 'pointerdown', 100, 100);
54
+ dispatchPointerEvent(renderer._r.domElement, 'pointerup', 103, 104);
55
+
56
+ expect(raycastCalls).to.equal(1);
57
+ });
58
+
59
+ it('should not raycast on pointerup after a drag larger than the threshold', function () {
60
+ let raycastCalls = 0;
61
+ renderer._raycastClick = () => {
62
+ raycastCalls++;
63
+ };
64
+
65
+ dispatchPointerEvent(renderer._r.domElement, 'pointerdown', 100, 100);
66
+ dispatchPointerEvent(renderer._r.domElement, 'pointerup', 110, 100);
67
+
68
+ expect(raycastCalls).to.equal(0);
69
+ });
70
+
71
+ it('should remove pointer listeners during dispose', function () {
72
+ let raycastCalls = 0;
73
+ const canvas = renderer._r.domElement;
74
+ renderer._raycastClick = () => {
75
+ raycastCalls++;
76
+ };
77
+
78
+ renderer.dispose();
79
+ renderer = null;
80
+
81
+ dispatchPointerEvent(canvas, 'pointerdown', 100, 100);
82
+ dispatchPointerEvent(canvas, 'pointerup', 100, 100);
83
+
84
+ expect(raycastCalls).to.equal(0);
85
+ });
86
+
87
+ it('should ignore non-primary pointer events', function () {
88
+ let raycastCalls = 0;
89
+ renderer._raycastClick = () => {
90
+ raycastCalls++;
91
+ };
92
+
93
+ dispatchPointerEvent(renderer._r.domElement, 'pointerdown', 100, 100, { isPrimary: false });
94
+ dispatchPointerEvent(renderer._r.domElement, 'pointerup', 100, 100, { isPrimary: false });
95
+
96
+ expect(raycastCalls).to.equal(0);
97
+ });
98
+
99
+ it('should not raycast after pointercancel', function () {
100
+ let raycastCalls = 0;
101
+ renderer._raycastClick = () => {
102
+ raycastCalls++;
103
+ };
104
+
105
+ dispatchPointerEvent(renderer._r.domElement, 'pointerdown', 100, 100);
106
+ dispatchPointerEvent(renderer._r.domElement, 'pointercancel', 100, 100);
107
+ dispatchPointerEvent(renderer._r.domElement, 'pointerup', 100, 100);
108
+
109
+ expect(raycastCalls).to.equal(0);
110
+ });
111
+
112
+ it('should convert document coordinates using the canvas bounding rect', function () {
113
+ renderer._r.domElement.getBoundingClientRect = () => ({
114
+ left: 40,
115
+ top: 20,
116
+ width: 200,
117
+ height: 100,
118
+ });
119
+
120
+ const vector = renderer.documentToWorld(140, 70);
121
+
122
+ expect(vector.x).to.equal(0);
123
+ expect(vector.y).to.equal(0);
124
+ });
125
+
126
+ it('should reuse the shared NDC vector', function () {
127
+ renderer._r.domElement.getBoundingClientRect = () => ({
128
+ left: 0,
129
+ top: 0,
130
+ width: 320,
131
+ height: 240,
132
+ });
133
+
134
+ const first = renderer.documentToWorld(160, 120);
135
+ const second = renderer.documentToWorld(80, 60);
136
+
137
+ expect(second).to.equal(first);
138
+ expect(second.x).to.equal(-0.5);
139
+ expect(second.y).to.equal(0.5);
140
+ });
141
+
142
+ it('should reuse the shared raycaster instance', function () {
143
+ let setFromCameraCalls = 0;
144
+ const sharedRaycaster = {
145
+ setFromCamera(vector, camera) {
146
+ setFromCameraCalls++;
147
+ expect(camera).to.equal(renderer._c);
148
+ expect(vector.x).to.equal(0);
149
+ expect(vector.y).to.equal(0);
150
+ },
151
+ intersectObjects() {
152
+ return [];
153
+ },
154
+ };
155
+
156
+ renderer._r.domElement.getBoundingClientRect = () => ({
157
+ left: 0,
158
+ top: 0,
159
+ width: 320,
160
+ height: 240,
161
+ });
162
+ renderer._raycaster = sharedRaycaster;
163
+
164
+ renderer._raycastClick({ clientX: 160, clientY: 120 });
165
+
166
+ expect(setFromCameraCalls).to.equal(1);
167
+ });
168
+ });
@@ -31,6 +31,8 @@ setGlobal('document', dom.window.document);
31
31
  setGlobal('navigator', dom.window.navigator);
32
32
  setGlobal('HTMLElement', dom.window.HTMLElement);
33
33
  setGlobal('HTMLCanvasElement', dom.window.HTMLCanvasElement);
34
+ setGlobal('AbortController', dom.window.AbortController);
35
+ setGlobal('AbortSignal', dom.window.AbortSignal);
34
36
  setGlobal('Image', dom.window.Image);
35
37
  setGlobal('ImageData', dom.window.ImageData);
36
38
  setGlobal('XMLHttpRequest', dom.window.XMLHttpRequest);
@@ -48,19 +50,73 @@ const _origGetContext = canvasProto.getContext;
48
50
  canvasProto.getContext = function (type, ...args) {
49
51
  if (type === 'webgl' || type === 'webgl2' || type === 'experimental-webgl') {
50
52
  // Return a minimal WebGL stub that THREE can interrogate without causing
51
- // errors. Only the methods referenced during renderer initialisation
53
+ // errors. Only the methods referenced during renderer initialisation
52
54
  // need to be present.
53
- return {
55
+ const gl = {
56
+ VERSION: 0x1F02,
57
+ VENDOR: 0x1F00,
58
+ RENDERER: 0x1F01,
59
+ SHADING_LANGUAGE_VERSION: 0x8B8C,
60
+ MAX_TEXTURE_IMAGE_UNITS: 0x8872,
61
+ MAX_VERTEX_TEXTURE_IMAGE_UNITS: 0x8B4C,
62
+ MAX_TEXTURE_SIZE: 0x0D33,
63
+ MAX_CUBE_MAP_TEXTURE_SIZE: 0x851C,
64
+ MAX_VERTEX_ATTRIBS: 0x8869,
65
+ MAX_VERTEX_UNIFORM_VECTORS: 0x8DFB,
66
+ MAX_VARYING_VECTORS: 0x8DFC,
67
+ MAX_FRAGMENT_UNIFORM_VECTORS: 0x8DFD,
68
+ MAX_SAMPLES: 0x8D57,
69
+ FRAMEBUFFER: 0x8D40,
70
+ FRAMEBUFFER_COMPLETE: 0x8CD5,
54
71
  canvas: this,
55
72
  drawingBufferWidth: 300,
56
73
  drawingBufferHeight: 150,
74
+ getContextAttributes: () => ({
75
+ alpha: true,
76
+ depth: true,
77
+ stencil: true,
78
+ antialias: false,
79
+ premultipliedAlpha: true,
80
+ preserveDrawingBuffer: false,
81
+ powerPreference: 'default',
82
+ failIfMajorPerformanceCaveat: false,
83
+ }),
84
+ getSupportedExtensions: () => [],
57
85
  getExtension: () => null,
58
- getParameter: () => null,
86
+ getParameter: (pname) => {
87
+ switch (pname) {
88
+ case gl.VERSION:
89
+ return 'WebGL 1.0';
90
+ case gl.VENDOR:
91
+ return 'jsdom';
92
+ case gl.RENDERER:
93
+ return 'jsdom WebGL stub';
94
+ case gl.SHADING_LANGUAGE_VERSION:
95
+ return 'WebGL GLSL ES 1.0';
96
+ case gl.MAX_TEXTURE_IMAGE_UNITS:
97
+ case gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS:
98
+ return 16;
99
+ case gl.MAX_TEXTURE_SIZE:
100
+ case gl.MAX_CUBE_MAP_TEXTURE_SIZE:
101
+ return 4096;
102
+ case gl.MAX_VERTEX_ATTRIBS:
103
+ return 16;
104
+ case gl.MAX_VERTEX_UNIFORM_VECTORS:
105
+ case gl.MAX_VARYING_VECTORS:
106
+ case gl.MAX_FRAGMENT_UNIFORM_VECTORS:
107
+ return 1024;
108
+ case gl.MAX_SAMPLES:
109
+ return 4;
110
+ default:
111
+ return 0;
112
+ }
113
+ },
59
114
  getShaderPrecisionFormat: () => ({ rangeMin: 127, rangeMax: 127, precision: 23 }),
60
115
  createTexture: () => ({}),
61
116
  bindTexture: () => {},
62
117
  texParameteri: () => {},
63
118
  pixelStorei: () => {},
119
+ activeTexture: () => {},
64
120
  enable: () => {},
65
121
  disable: () => {},
66
122
  blendEquation: () => {},
@@ -93,14 +149,18 @@ canvasProto.getContext = function (type, ...args) {
93
149
  compileShader: () => {},
94
150
  attachShader: () => {},
95
151
  linkProgram: () => {},
152
+ getProgramInfoLog: () => '',
96
153
  getProgramParameter: (p, pname) => {
97
154
  // LINK_STATUS
98
155
  if (pname === 35714) return true;
99
156
  return null;
100
157
  },
101
158
  getShaderParameter: () => true,
159
+ getShaderInfoLog: () => '',
102
160
  getUniformLocation: () => ({}),
103
161
  getAttribLocation: () => 0,
162
+ getActiveAttrib: () => null,
163
+ getActiveUniform: () => null,
104
164
  uniform1i: () => {},
105
165
  uniform1f: () => {},
106
166
  uniform2f: () => {},
@@ -132,6 +192,7 @@ canvasProto.getContext = function (type, ...args) {
132
192
  blitFramebuffer: () => {},
133
193
  readBuffer: () => {},
134
194
  drawBuffers: () => {},
195
+ checkFramebufferStatus: () => gl.FRAMEBUFFER_COMPLETE,
135
196
  renderbufferStorageMultisample: () => {},
136
197
  createSampler: () => ({}),
137
198
  deleteSampler: () => {},
@@ -139,6 +200,7 @@ canvasProto.getContext = function (type, ...args) {
139
200
  samplerParameteri: () => {},
140
201
  samplerParameterf: () => {},
141
202
  };
203
+ return gl;
142
204
  }
143
205
  if (_origGetContext) {
144
206
  return _origGetContext.call(this, type, ...args);
@@ -1 +0,0 @@
1
- {"list":[{"title":"lib/model.module:js","link":"<a href=\"lib_model.module_js.html\">lib/model.js</a>","description":"<p>Class holding the atomic models to be plotted</p>"},{"title":"lib/model.module:js~AtomImage","link":"<a href=\"lib_model.module_js-AtomImage.html\">AtomImage</a>"},{"title":"lib/model.module:js~AtomImage#addEllipsoid","link":"<a href=\"lib_model.module_js-AtomImage.html#addEllipsoid\">addEllipsoid</a>","description":"<p>Add an ellipsoid to the atom.</p>"},{"title":"lib/model.module:js~AtomImage#addLabel","link":"<a href=\"lib_model.module_js-AtomImage.html#addLabel\">addLabel</a>","description":"<p>Add a text label to the atom.</p>"},{"title":"lib/model.module:js~AtomImage#aura","link":"<a href=\"lib_model.module_js-AtomImage.html#aura\">aura</a>","description":"<p>Aura used to highlight this atom image</p>"},{"title":"lib/model.module:js~AtomImage#baseRadius","link":"<a href=\"lib_model.module_js-AtomImage.html#baseRadius\">baseRadius</a>","description":"<p>Starting radius of the atom</p>"},{"title":"lib/model.module:js~AtomImage#bondedAtoms","link":"<a href=\"lib_model.module_js-AtomImage.html#bondedAtoms\">bondedAtoms</a>","description":"<p>All atoms bonded to this atom</p>"},{"title":"lib/model.module:js~AtomImage#bonds","link":"<a href=\"lib_model.module_js-AtomImage.html#bonds\">bonds</a>","description":"<p>All bonds connected to this atom</p>"},{"title":"lib/model.module:js~AtomImage#bondsFrom","link":"<a href=\"lib_model.module_js-AtomImage.html#bondsFrom\">bondsFrom</a>","description":"<p>Bonds from this atom</p>"},{"title":"lib/model.module:js~AtomImage#bondsTo","link":"<a href=\"lib_model.module_js-AtomImage.html#bondsTo\">bondsTo</a>","description":"<p>Bonds to this atom</p>"},{"title":"lib/model.module:js~AtomImage#color","link":"<a href=\"lib_model.module_js-AtomImage.html#color\">color</a>","description":"<p>Color of the atom</p>"},{"title":"lib/model.module:js~AtomImage#cpkColor","link":"<a href=\"lib_model.module_js-AtomImage.html#cpkColor\">cpkColor</a>","description":"<p>Hex integer code of the conventional CPK color used for this element\n(altered in case of non-standard isotopes)</p>"},{"title":"lib/model.module:js~AtomImage#crystLabel","link":"<a href=\"lib_model.module_js-AtomImage.html#crystLabel\">crystLabel</a>","description":"<p>Crystal site label of this atom</p>"},{"title":"lib/model.module:js~AtomImage#element","link":"<a href=\"lib_model.module_js-AtomImage.html#element\">element</a>","description":"<p>Symbol of this atom's element</p>"},{"title":"lib/model.module:js~AtomImage#elementData","link":"<a href=\"lib_model.module_js-AtomImage.html#elementData\">elementData</a>","description":"<p>Periodic table information for this atom's element</p>"},{"title":"lib/model.module:js~AtomImage#ellipsoidProperty","link":"<a href=\"lib_model.module_js-AtomImage.html#ellipsoidProperty\">ellipsoidProperty</a>","description":"<p>Retrieve or set an ellipsoid's properties</p>"},{"title":"lib/model.module:js~AtomImage#fxyz","link":"<a href=\"lib_model.module_js-AtomImage.html#fxyz\">fxyz</a>","description":"<p>Fractional coordinates of this atom image</p>"},{"title":"lib/model.module:js~AtomImage#fxyz0","link":"<a href=\"lib_model.module_js-AtomImage.html#fxyz0\">fxyz0</a>","description":"<p>Fractional coordinates of this atom's original</p>"},{"title":"lib/model.module:js~AtomImage#getArrayValue","link":"<a href=\"lib_model.module_js-AtomImage.html#getArrayValue\">getArrayValue</a>","description":"<p>Get the value for one array for this image</p>"},{"title":"lib/model.module:js~AtomImage#highlighted","link":"<a href=\"lib_model.module_js-AtomImage.html#highlighted\">highlighted</a>","description":"<p>Whether the atom is highlighted</p>"},{"title":"lib/model.module:js~AtomImage#id","link":"<a href=\"lib_model.module_js-AtomImage.html#id\">id</a>","description":"<p>String ID of the image</p>"},{"title":"lib/model.module:js~AtomImage#ijk","link":"<a href=\"lib_model.module_js-AtomImage.html#ijk\">ijk</a>","description":"<p>Cell indices of this atom image</p>"},{"title":"lib/model.module:js~AtomImage#imgIndex","link":"<a href=\"lib_model.module_js-AtomImage.html#imgIndex\">imgIndex</a>","description":"<p>Index of this image</p>"},{"title":"lib/model.module:js~AtomImage#index","link":"<a href=\"lib_model.module_js-AtomImage.html#index\">index</a>","description":"<p>Index of the atom</p>"},{"title":"lib/model.module:js~AtomImage#isotope","link":"<a href=\"lib_model.module_js-AtomImage.html#isotope\">isotope</a>","description":"<p>Atomic mass of this atom's isotope</p>"},{"title":"lib/model.module:js~AtomImage#isotopeData","link":"<a href=\"lib_model.module_js-AtomImage.html#isotopeData\">isotopeData</a>","description":"<p>Information for this atom's isotope</p>"},{"title":"lib/model.module:js~AtomImage#isotopeGlobal","link":"<a href=\"lib_model.module_js-AtomImage.html#isotopeGlobal\">isotopeGlobal</a>","description":"<p>Atomic mass of the global isotope set as default for this atom's species</p>"},{"title":"lib/model.module:js~AtomImage#labelProperty","link":"<a href=\"lib_model.module_js-AtomImage.html#labelProperty\">labelProperty</a>","description":"<p>Retrieve or set a label's properties</p>"},{"title":"lib/model.module:js~AtomImage#mesh","link":"<a href=\"lib_model.module_js-AtomImage.html#mesh\">mesh</a>","description":"<p>Mesh corresponding to this atom image</p>"},{"title":"lib/model.module:js~AtomImage#model","link":"<a href=\"lib_model.module_js-AtomImage.html#model\">model</a>","description":"<p>Model this atom belongs to</p>"},{"title":"lib/model.module:js~AtomImage#moleculeIndex","link":"<a href=\"lib_model.module_js-AtomImage.html#moleculeIndex\">moleculeIndex</a>","description":"<p>Index of the molecule this atom belongs to</p>"},{"title":"lib/model.module:js~AtomImage#number","link":"<a href=\"lib_model.module_js-AtomImage.html#number\">number</a>","description":"<p>Atomic number of element</p>"},{"title":"lib/model.module:js~AtomImage#opacity","link":"<a href=\"lib_model.module_js-AtomImage.html#opacity\">opacity</a>","description":"<p>Opacity of the atom</p>"},{"title":"lib/model.module:js~AtomImage#radius","link":"<a href=\"lib_model.module_js-AtomImage.html#radius\">radius</a>","description":"<p>Final radius of the atom (starting radius * scale)</p>"},{"title":"lib/model.module:js~AtomImage#removeEllipsoid","link":"<a href=\"lib_model.module_js-AtomImage.html#removeEllipsoid\">removeEllipsoid</a>","description":"<p>Remove the ellipsoid with a given name</p>"},{"title":"lib/model.module:js~AtomImage#removeLabel","link":"<a href=\"lib_model.module_js-AtomImage.html#removeLabel\">removeLabel</a>","description":"<p>Remove the label of a given name</p>"},{"title":"lib/model.module:js~AtomImage#renderer","link":"<a href=\"lib_model.module_js-AtomImage.html#renderer\">renderer</a>","description":"<p>Renderer used by this atom</p>"},{"title":"lib/model.module:js~AtomImage#scale","link":"<a href=\"lib_model.module_js-AtomImage.html#scale\">scale</a>","description":"<p>Scale of the atom</p>"},{"title":"lib/model.module:js~AtomImage#speciesIndex","link":"<a href=\"lib_model.module_js-AtomImage.html#speciesIndex\">speciesIndex</a>","description":"<p>Index of the species of this atom</p>"},{"title":"lib/model.module:js~AtomImage#vdwRadius","link":"<a href=\"lib_model.module_js-AtomImage.html#vdwRadius\">vdwRadius</a>","description":"<p>Van dew Waals radius for this element</p>"},{"title":"lib/model.module:js~AtomImage#visible","link":"<a href=\"lib_model.module_js-AtomImage.html#visible\">visible</a>","description":"<p>Whether the atom is visible</p>"},{"title":"lib/model.module:js~AtomImage#xyz","link":"<a href=\"lib_model.module_js-AtomImage.html#xyz\">xyz</a>","description":"<p>Position of this atom image</p>"},{"title":"lib/model.module:js~AtomImage#xyz0","link":"<a href=\"lib_model.module_js-AtomImage.html#xyz0\">xyz0</a>","description":"<p>Position of this atom's original</p>"},{"title":"lib/model.module:js~BondImage","link":"<a href=\"lib_model.module_js-BondImage.html\">BondImage</a>"},{"title":"lib/model.module:js~BondImage#atom1","link":"<a href=\"lib_model.module_js-BondImage.html#atom1\">atom1</a>","description":"<p>First atom connected to this bond</p>"},{"title":"lib/model.module:js~BondImage#atom2","link":"<a href=\"lib_model.module_js-BondImage.html#atom2\">atom2</a>","description":"<p>Second atom connected to this bond</p>"},{"title":"lib/model.module:js~BondImage#color1","link":"<a href=\"lib_model.module_js-BondImage.html#color1\">color1</a>","description":"<p>First color of the bond</p>"},{"title":"lib/model.module:js~BondImage#color2","link":"<a href=\"lib_model.module_js-BondImage.html#color2\">color2</a>","description":"<p>Second color of the bond</p>"},{"title":"lib/model.module:js~BondImage#key","link":"<a href=\"lib_model.module_js-BondImage.html#key\">key</a>","description":"<p>A unique string key used to quickly reference the bond</p>"},{"title":"lib/model.module:js~BondImage#length","link":"<a href=\"lib_model.module_js-BondImage.html#length\">length</a>","description":"<p>Bond length in Angstroms</p>"},{"title":"lib/model.module:js~BondImage#mesh","link":"<a href=\"lib_model.module_js-BondImage.html#mesh\">mesh</a>","description":"<p>Mesh corresponding to this bond image</p>"},{"title":"lib/model.module:js~BondImage#model","link":"<a href=\"lib_model.module_js-BondImage.html#model\">model</a>","description":"<p>Model this bond belongs to</p>"},{"title":"lib/model.module:js~BondImage#opacity1","link":"<a href=\"lib_model.module_js-BondImage.html#opacity1\">opacity1</a>","description":"<p>First opacity of the bond</p>"},{"title":"lib/model.module:js~BondImage#opacity2","link":"<a href=\"lib_model.module_js-BondImage.html#opacity2\">opacity2</a>","description":"<p>Second opacity of the bond</p>"},{"title":"lib/model.module:js~BondImage#radius","link":"<a href=\"lib_model.module_js-BondImage.html#radius\">radius</a>","description":"<p>Radius of the bond</p>"},{"title":"lib/model.module:js~BondImage#renderer","link":"<a href=\"lib_model.module_js-BondImage.html#renderer\">renderer</a>","description":"<p>Renderer used by this bond</p>"},{"title":"lib/model.module:js~BondImage#visible","link":"<a href=\"lib_model.module_js-BondImage.html#visible\">visible</a>","description":"<p>Whether the bond is visible</p>"},{"title":"lib/model.module:js~Model","link":"<a href=\"lib_model.module_js-Model.html\">Model</a>","description":"<p>An object containing an Atomic structure and taking care of its periodic\nnature, allowing querying and selection, and so on.</p>"},{"title":"lib/model.module:js~Model#absToFrac","link":"<a href=\"lib_model.module_js-Model.html#absToFrac\">absToFrac</a>","description":"<p>Convert absolute coordinates to fractional</p>"},{"title":"lib/model.module:js~Model#addLink","link":"<a href=\"lib_model.module_js-Model.html#addLink\">addLink</a>","description":"<p>Add link drawn on model</p>"},{"title":"lib/model.module:js~Model#addSphere","link":"<a href=\"lib_model.module_js-Model.html#addSphere\">addSphere</a>","description":"<p>Add a sphere drawn on model</p>"},{"title":"lib/model.module:js~Model#all","link":"<a href=\"lib_model.module_js-Model.html#all\">all</a>","description":"<p>ModelView containing all the atoms of the image</p>"},{"title":"lib/model.module:js~Model#atoms","link":"<a href=\"lib_model.module_js-Model.html#atoms\">atoms</a>","description":"<p>Atom images in this model</p>"},{"title":"lib/model.module:js~Model#axes","link":"<a href=\"lib_model.module_js-Model.html#axes\">axes</a>","description":"<p>Graphical object representing the unit cell's axes</p>"},{"title":"lib/model.module:js~Model#box","link":"<a href=\"lib_model.module_js-Model.html#box\">box</a>","description":"<p>Graphical object representing the unit cell's box</p>"},{"title":"lib/model.module:js~Model#cell","link":"<a href=\"lib_model.module_js-Model.html#cell\">cell</a>","description":"<p>Unit cell of the model's original cell</p>"},{"title":"lib/model.module:js~Model#clearGraphics","link":"<a href=\"lib_model.module_js-Model.html#clearGraphics\">clearGraphics</a>","description":"<p>Remove all graphical objects</p>"},{"title":"lib/model.module:js~Model#crystalLabels","link":"<a href=\"lib_model.module_js-Model.html#crystalLabels\">crystalLabels</a>","description":"<p>Crystallographic labels of each atom</p>"},{"title":"lib/model.module:js~Model#deleteArray","link":"<a href=\"lib_model.module_js-Model.html#deleteArray\">deleteArray</a>","description":"<p>Delete an array from the underlying Atoms object</p>"},{"title":"lib/model.module:js~Model#find","link":"<a href=\"lib_model.module_js-Model.html#find\">find</a>","description":"<p>Find a group of atoms based on a given query and return as AtomImages</p>"},{"title":"lib/model.module:js~Model#fracToAbs","link":"<a href=\"lib_model.module_js-Model.html#fracToAbs\">fracToAbs</a>","description":"<p>Convert fractional coordinates to absolute</p>"},{"title":"lib/model.module:js~Model#getArray","link":"<a href=\"lib_model.module_js-Model.html#getArray\">getArray</a>","description":"<p>Retrieve an array from the underlying Atoms object</p>"},{"title":"lib/model.module:js~Model#hasArray","link":"<a href=\"lib_model.module_js-Model.html#hasArray\">hasArray</a>","description":"<p>Check if an array exists in the underlying Atoms object</p>"},{"title":"lib/model.module:js~Model#info","link":"<a href=\"lib_model.module_js-Model.html#info\">info</a>","description":"<p>Additional information from the model's original cell</p>"},{"title":"lib/model.module:js~Model#length","link":"<a href=\"lib_model.module_js-Model.html#length\">length</a>","description":"<p>Number of atoms in this model's original cell</p>"},{"title":"lib/model.module:js~Model#minimumSupercell","link":"<a href=\"lib_model.module_js-Model.html#minimumSupercell\">minimumSupercell</a>","description":"<p>Compute and return the minimum supercell that guarantees\ncontaining all atoms at a maximum distance r from those in the\n[0,0,0] cell.</p>"},{"title":"lib/model.module:js~Model#numbers","link":"<a href=\"lib_model.module_js-Model.html#numbers\">numbers</a>","description":"<p>Atomic numbers in this model's original cell</p>"},{"title":"lib/model.module:js~Model#pbc","link":"<a href=\"lib_model.module_js-Model.html#pbc\">pbc</a>","description":"<p>Periodic boundary conditions</p>"},{"title":"lib/model.module:js~Model#periodic","link":"<a href=\"lib_model.module_js-Model.html#periodic\">periodic</a>","description":"<p>Whether this model is periodic in all three directions of space</p>"},{"title":"lib/model.module:js~Model#positions","link":"<a href=\"lib_model.module_js-Model.html#positions\">positions</a>","description":"<p>Coordinates of the atoms in this model's original cell</p>"},{"title":"lib/model.module:js~Model#removeGraphics","link":"<a href=\"lib_model.module_js-Model.html#removeGraphics\">removeGraphics</a>","description":"<p>Remove the graphical object with a given name</p>"},{"title":"lib/model.module:js~Model#renderer","link":"<a href=\"lib_model.module_js-Model.html#renderer\">renderer</a>","description":"<p>Renderer used for this model's graphics</p>"},{"title":"lib/model.module:js~Model#scaledPositions","link":"<a href=\"lib_model.module_js-Model.html#scaledPositions\">scaledPositions</a>","description":"<p>Fractional coordinates of the atoms in this model's original cell</p>"},{"title":"lib/model.module:js~Model#setArray","link":"<a href=\"lib_model.module_js-Model.html#setArray\">setArray</a>","description":"<p>Set an array for the underlying Atoms object</p>"},{"title":"lib/model.module:js~Model#speciesIndices","link":"<a href=\"lib_model.module_js-Model.html#speciesIndices\">speciesIndices</a>","description":"<p>Indices of each atom by their species (e.g. C1, C2, H1, C3, H2, etc.)</p>"},{"title":"lib/model.module:js~Model#supercell","link":"<a href=\"lib_model.module_js-Model.html#supercell\">supercell</a>","description":"<p>Shape of the supercell for this model</p>"},{"title":"lib/model.module:js~Model#supercellGrid","link":"<a href=\"lib_model.module_js-Model.html#supercellGrid\">supercellGrid</a>","description":"<p>Full grid of origin coordinates of the cells making up the supercell</p>"},{"title":"lib/model.module:js~Model#symbols","link":"<a href=\"lib_model.module_js-Model.html#symbols\">symbols</a>","description":"<p>Chemical symbols in this model's original cell</p>"},{"title":"lib/model.module:js~Model#vdwElementScaling","link":"<a href=\"lib_model.module_js-Model.html#vdwElementScaling\">vdwElementScaling</a>","description":"<p>Table of scaling factors by element for Van der Waals radii</p>"},{"title":"lib/model.module:js~Model#vdwScaling","link":"<a href=\"lib_model.module_js-Model.html#vdwScaling\">vdwScaling</a>","description":"<p>Global scaling factor for Van der Waals radii</p>"},{"title":"lib/model.module:js~Model#view","link":"<a href=\"lib_model.module_js-Model.html#view\">view</a>","description":"<p>Create a new ModelView for this model, using a given list of indices</p>"},{"title":"lib/model.module:js~Model#viewFromIndices","link":"<a href=\"lib_model.module_js-Model.html#viewFromIndices\">viewFromIndices</a>","description":"<p>Reconstruct a {@link ModelView} from a plain array of atom-image indices,\nas produced by {@link ModelView#toIndices}. This is the stable public API\nfor deserialising a saved selection.</p>"},{"title":"lib/model.module:js~Model#viewFromLabels","link":"<a href=\"lib_model.module_js-Model.html#viewFromLabels\">viewFromLabels</a>","description":"<p>Reconstruct a {@link ModelView} from an array of crystallographic site\nlabels (<code>crystLabel</code>), as produced by {@link ModelView#toLabels}. This\nis resilient to atom-index reordering across reloads.</p>"},{"title":"lib/modelview.module:js","link":"<a href=\"lib_modelview.module_js.html\">lib/modelview.js</a>","description":"<p>Class holding &quot;model views&quot;, subsets of atoms in a Model used\nfor selection or to perform operations in block</p>"},{"title":"lib/modelview.module:js~ModelView","link":"<a href=\"lib_modelview.module_js-ModelView.html\">ModelView</a>"},{"title":"lib/modelview.module:js~ModelView#addEllipsoids","link":"<a href=\"lib_modelview.module_js-ModelView.html#addEllipsoids\">addEllipsoids</a>","description":"<p>Add ellipsoids to the atom images in this ModelView</p>"},{"title":"lib/modelview.module:js~ModelView#addLabels","link":"<a href=\"lib_modelview.module_js-ModelView.html#addLabels\">addLabels</a>","description":"<p>Add labels to the atom images in this ModelView</p>"},{"title":"lib/modelview.module:js~ModelView#and","link":"<a href=\"lib_modelview.module_js-ModelView.html#and\">and</a>","description":"<p>Intersection with another ModelView</p>"},{"title":"lib/modelview.module:js~ModelView#atoms","link":"<a href=\"lib_modelview.module_js-ModelView.html#atoms\">atoms</a>","description":"<p>Atom images in this view</p>"},{"title":"lib/modelview.module:js~ModelView#elements","link":"<a href=\"lib_modelview.module_js-ModelView.html#elements\">elements</a>","description":"<p>Get sorted set of unique elements in the ModelView</p>"},{"title":"lib/modelview.module:js~ModelView#ellipsoidProperties","link":"<a href=\"lib_modelview.module_js-ModelView.html#ellipsoidProperties\">ellipsoidProperties</a>","description":"<p>Get or set ellipsoids' properties for the atom images in this ModelView</p>"},{"title":"lib/modelview.module:js~ModelView#find","link":"<a href=\"lib_modelview.module_js-ModelView.html#find\">find</a>","description":"<p>Perform a further search within the atoms included in this ModelView.</p>"},{"title":"lib/modelview.module:js~ModelView#hide","link":"<a href=\"lib_modelview.module_js-ModelView.html#hide\">hide</a>","description":"<p>Make all atoms in the view invisible. Can be chained</p>"},{"title":"lib/modelview.module:js~ModelView#indices","link":"<a href=\"lib_modelview.module_js-ModelView.html#indices\">indices</a>","description":"<p>Indices of the atom images in this view</p>"},{"title":"lib/modelview.module:js~ModelView#labelProperties","link":"<a href=\"lib_modelview.module_js-ModelView.html#labelProperties\">labelProperties</a>","description":"<p>Get or set labels' properties for the atom images in this ModelView</p>"},{"title":"lib/modelview.module:js~ModelView#length","link":"<a href=\"lib_modelview.module_js-ModelView.html#length\">length</a>","description":"<p>Number of atom images in this view</p>"},{"title":"lib/modelview.module:js~ModelView#map","link":"<a href=\"lib_modelview.module_js-ModelView.html#map\">map</a>","description":"<p>Run a function on each AtomImage, returning an Array of the results.</p>"},{"title":"lib/modelview.module:js~ModelView#model","link":"<a href=\"lib_modelview.module_js-ModelView.html#model\">model</a>","description":"<p>Model used by this view</p>"},{"title":"lib/modelview.module:js~ModelView#not","link":"<a href=\"lib_modelview.module_js-ModelView.html#not\">not</a>","description":"<p>Complement to this ModelView</p>"},{"title":"lib/modelview.module:js~ModelView#or","link":"<a href=\"lib_modelview.module_js-ModelView.html#or\">or</a>","description":"<p>Union with another ModelView</p>"},{"title":"lib/modelview.module:js~ModelView#remove","link":"<a href=\"lib_modelview.module_js-ModelView.html#remove\">remove</a>","description":"<p>Remove all atoms in mview from the current view</p>"},{"title":"lib/modelview.module:js~ModelView#removeEllipsoids","link":"<a href=\"lib_modelview.module_js-ModelView.html#removeEllipsoids\">removeEllipsoids</a>","description":"<p>Remove ellipsoids from the atom images in this ModelView</p>"},{"title":"lib/modelview.module:js~ModelView#removeLabels","link":"<a href=\"lib_modelview.module_js-ModelView.html#removeLabels\">removeLabels</a>","description":"<p>Remove labels from the atom images in this ModelView</p>"},{"title":"lib/modelview.module:js~ModelView#setProperty","link":"<a href=\"lib_modelview.module_js-ModelView.html#setProperty\">setProperty</a>","description":"<p>Set some property of the atoms within the ModelView.</p>"},{"title":"lib/modelview.module:js~ModelView#show","link":"<a href=\"lib_modelview.module_js-ModelView.html#show\">show</a>","description":"<p>Make all atoms in the view visible. Can be chained</p>"},{"title":"lib/modelview.module:js~ModelView#toIndices","link":"<a href=\"lib_modelview.module_js-ModelView.html#toIndices\">toIndices</a>","description":"<p>Return a plain array of the atom-image indices in this view.\nUse this to serialise a selection; restore it with\n{@link Model#viewFromIndices}.</p>"},{"title":"lib/modelview.module:js~ModelView#toLabels","link":"<a href=\"lib_modelview.module_js-ModelView.html#toLabels\">toLabels</a>","description":"<p>Return the crystallographic site labels (<code>crystLabel</code>) of the atoms\nin this view. Use this to serialise a selection in a way that is\nrobust to atom reordering; restore with {@link Model#viewFromLabels}.</p>"},{"title":"lib/modelview.module:js~ModelView#uniqueSites","link":"<a href=\"lib_modelview.module_js-ModelView.html#uniqueSites\">uniqueSites</a>","description":"<p>Unique atoms in the current view (based on site labels)</p>"},{"title":"lib/modelview.module:js~ModelView#unique_labels_multiplicity","link":"<a href=\"lib_modelview.module_js-ModelView.html#unique_labels_multiplicity\">unique_labels_multiplicity</a>","description":"<p>Multiplicity of the atoms in the view</p>"},{"title":"lib/modelview.module:js~ModelView#xor","link":"<a href=\"lib_modelview.module_js-ModelView.html#xor\">xor</a>","description":"<p>Exclusive OR with another ModelView</p>"},{"title":"lib/visualizer.module:js","link":"<a href=\"lib_visualizer.module_js.html\">lib/visualizer.js</a>","description":"<p>Class constituting the main object that plots crystals in the webpage</p>"},{"title":"lib/visualizer.module:js~CrystVis","link":"<a href=\"lib_visualizer.module_js-CrystVis.html\">CrystVis</a>","description":"<p>An object providing a full interface to a renderer for crystallographic\nmodels</p>"},{"title":"lib/visualizer.module:js~CrystVis#addNotification","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#addNotification\">addNotification</a>","description":"<p>Add a notification to the list of notifications to be displayed</p>"},{"title":"lib/visualizer.module:js~CrystVis#addNotifications","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#addNotifications\">addNotifications</a>","description":"<p>Adds all notifications to the drawing</p>"},{"title":"lib/visualizer.module:js~CrystVis#addPrimitive","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#addPrimitive\">addPrimitive</a>","description":"<p>Add a primitive shape to the drawing</p>"},{"title":"lib/visualizer.module:js~CrystVis#clearNotifications","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#clearNotifications\">clearNotifications</a>","description":"<p>Removes notifications from the drawing</p>"},{"title":"lib/visualizer.module:js~CrystVis#deleteModel","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#deleteModel\">deleteModel</a>","description":"<p>Erase a model from the recorded ones</p>"},{"title":"lib/visualizer.module:js~CrystVis#displayModel","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#displayModel\">displayModel</a>","description":"<p>Render a model</p>"},{"title":"lib/visualizer.module:js~CrystVis#displayed","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#displayed\">displayed</a>","description":"<p>Displayed atoms</p>"},{"title":"lib/visualizer.module:js~CrystVis#dispose","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#dispose\">dispose</a>","description":"<p>Release all resources held by this instance: cancels the animation loop,\nremoves all canvas event listeners, disposes OrbitControls and the\nTHREE.WebGLRenderer, and nulls internal references. After calling this\nmethod the instance must not be used again.</p>"},{"title":"lib/visualizer.module:js~CrystVis#getCameraState","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#getCameraState\">getCameraState</a>","description":"<p>Return a plain serialisable snapshot of the current camera state.</p>"},{"title":"lib/visualizer.module:js~CrystVis#getModelMeta","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#getModelMeta\">getModelMeta</a>","description":"<p>Return metadata stored alongside the named model:\n<code>{ prefix, originalName }</code>.</p>"},{"title":"lib/visualizer.module:js~CrystVis#getModelParameters","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#getModelParameters\">getModelParameters</a>","description":"<p>Return the loading parameters that were used when the named model was\nlast loaded / reloaded (a clone of the merged parameter object).</p>"},{"title":"lib/visualizer.module:js~CrystVis#getModelSource","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#getModelSource\">getModelSource</a>","description":"<p>Return the raw file text and format extension originally passed to\n<code>loadModels()</code> for the named model.</p>"},{"title":"lib/visualizer.module:js~CrystVis#getScreenshotData","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#getScreenshotData\">getScreenshotData</a>","description":"<p>Recover a data URL of a PNG screenshot of the current scene</p>"},{"title":"lib/visualizer.module:js~CrystVis#highlightSelected","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#highlightSelected\">highlightSelected</a>","description":"<p>Whether the selected atoms should be highlighted with auras</p>"},{"title":"lib/visualizer.module:js~CrystVis#isDisposed","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#isDisposed\">isDisposed</a>","description":"<p>Whether this instance has been disposed.\nOnce true, most methods will throw rather than silently fail.</p>"},{"title":"lib/visualizer.module:js~CrystVis#loadModels","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#loadModels\">loadModels</a>","description":"<p>Load one or more atomic models from a file's contents</p>"},{"title":"lib/visualizer.module:js~CrystVis#model","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#model\">model</a>","description":"<p>Currently loaded model</p>"},{"title":"lib/visualizer.module:js~CrystVis#modelList","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#modelList\">modelList</a>","description":"<p>List of loaded models</p>"},{"title":"lib/visualizer.module:js~CrystVis#modelName","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#modelName\">modelName</a>","description":"<p>Name of the currently loaded model</p>"},{"title":"lib/visualizer.module:js~CrystVis#onAtomBox","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#onAtomBox\">onAtomBox</a>","description":"<p>Set a callback function for an event where a user drags a box around multiple atoms.\nThe function should take as arguments a ModelView including the atoms in the box:</p>\n<p>function callback(view) {\n...\n}</p>"},{"title":"lib/visualizer.module:js~CrystVis#onAtomClick","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#onAtomClick\">onAtomClick</a>","description":"<p>Set a callback function for an event where a user clicks on an atom. The\nfunction should take as arguments the atom image for the clicked atom and\nthe event object:</p>\n<p>function callback(atom, event) {\n...\n}</p>"},{"title":"lib/visualizer.module:js~CrystVis#onCameraChange","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#onCameraChange\">onCameraChange</a>","description":"<p>Subscribe to camera-change events (rotate, pan, zoom).\nThe callback receives a snapshot identical to {@link CrystVis#getCameraState}.</p>"},{"title":"lib/visualizer.module:js~CrystVis#onDisplayChange","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#onDisplayChange\">onDisplayChange</a>","description":"<p>Subscribe to display-change events fired whenever <code>displayModel()</code> completes.\nThe callback receives the name of the newly displayed model (or <code>null</code> when cleared).</p>"},{"title":"lib/visualizer.module:js~CrystVis#onModelListChange","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#onModelListChange\">onModelListChange</a>","description":"<p>Subscribe to model-list change events (model added or deleted).\nThe callback receives the new list of model names.</p>"},{"title":"lib/visualizer.module:js~CrystVis#reloadModel","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#reloadModel\">reloadModel</a>","description":"<p>Reload a model, possibly with new parameters</p>"},{"title":"lib/visualizer.module:js~CrystVis#removePrimitive","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#removePrimitive\">removePrimitive</a>","description":"<p>Remove a primitive shape from the drawing</p>"},{"title":"lib/visualizer.module:js~CrystVis#selected","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#selected\">selected</a>","description":"<p>Selected atoms</p>"},{"title":"lib/visualizer.module:js~CrystVis#setCameraState","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#setCameraState\">setCameraState</a>","description":"<p>Restore a camera snapshot produced by {@link CrystVis#getCameraState}.\nSafe to call after <code>displayModel()</code>.</p>"},{"title":"lib/visualizer.module:js~CrystVis#theme","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#theme\">theme</a>","description":"<p>Theme</p>"},{"title":"lib/visualizer.module:js~CrystVis#unloadAll","link":"<a href=\"lib_visualizer.module_js-CrystVis.html#unloadAll\">unloadAll</a>","description":"<p>Remove <em>all</em> loaded models and reset the view in a single atomic operation\n(only one render pass after everything is cleared, unlike calling\n<code>deleteModel()</code> in a loop).</p>"}]}
Binary file
Binary file
Binary file
package/docs/index.html DELETED
@@ -1,59 +0,0 @@
1
- <!DOCTYPE html><html lang="en" style="font-size:16px"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Home</title><!--[if lt IE 9]>
2
- <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
3
- <![endif]--><script src="scripts/third-party/hljs.js" defer="defer"></script><script src="scripts/third-party/hljs-line-num.js" defer="defer"></script><script src="scripts/third-party/popper.js" defer="defer"></script><script src="scripts/third-party/tippy.js" defer="defer"></script><script src="scripts/third-party/tocbot.min.js"></script><script>var baseURL="/",locationPathname="";baseURL=(locationPathname=document.location.pathname).substr(0,locationPathname.lastIndexOf("/")+1)</script><link rel="stylesheet" href="styles/clean-jsdoc-theme.min.css"><svg aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none"><defs><symbol id="copy-icon" viewbox="0 0 488.3 488.3"><g><path d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z"/><path d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z"/></g></symbol><symbol id="search-icon" viewBox="0 0 512 512"><g><g><path d="M225.474,0C101.151,0,0,101.151,0,225.474c0,124.33,101.151,225.474,225.474,225.474 c124.33,0,225.474-101.144,225.474-225.474C450.948,101.151,349.804,0,225.474,0z M225.474,409.323 c-101.373,0-183.848-82.475-183.848-183.848S124.101,41.626,225.474,41.626s183.848,82.475,183.848,183.848 S326.847,409.323,225.474,409.323z"/></g></g><g><g><path d="M505.902,476.472L386.574,357.144c-8.131-8.131-21.299-8.131-29.43,0c-8.131,8.124-8.131,21.306,0,29.43l119.328,119.328 c4.065,4.065,9.387,6.098,14.715,6.098c5.321,0,10.649-2.033,14.715-6.098C514.033,497.778,514.033,484.596,505.902,476.472z"/></g></g></symbol><symbol id="font-size-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.246 15H4.754l-2 5H.6L7 4h2l6.4 16h-2.154l-2-5zm-.8-2L8 6.885 5.554 13h4.892zM21 12.535V12h2v8h-2v-.535a4 4 0 1 1 0-6.93zM19 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol><symbol id="add-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z"/></symbol><symbol id="minus-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 11h14v2H5z"/></symbol><symbol id="dark-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol><symbol id="light-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol><symbol id="reset-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10c0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 1 0-2.46 5.772l.997 1.795z"/></symbol><symbol id="down-icon" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.7803 6.21967C13.0732 6.51256 13.0732 6.98744 12.7803 7.28033L8.53033 11.5303C8.23744 11.8232 7.76256 11.8232 7.46967 11.5303L3.21967 7.28033C2.92678 6.98744 2.92678 6.51256 3.21967 6.21967C3.51256 5.92678 3.98744 5.92678 4.28033 6.21967L8 9.93934L11.7197 6.21967C12.0126 5.92678 12.4874 5.92678 12.7803 6.21967Z"></path></symbol><symbol id="codepen-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M16.5 13.202L13 15.535v3.596L19.197 15 16.5 13.202zM14.697 12L12 10.202 9.303 12 12 13.798 14.697 12zM20 10.869L18.303 12 20 13.131V10.87zM19.197 9L13 4.869v3.596l3.5 2.333L19.197 9zM7.5 10.798L11 8.465V4.869L4.803 9 7.5 10.798zM4.803 15L11 19.131v-3.596l-3.5-2.333L4.803 15zM4 13.131L5.697 12 4 10.869v2.262zM2 9a1 1 0 0 1 .445-.832l9-6a1 1 0 0 1 1.11 0l9 6A1 1 0 0 1 22 9v6a1 1 0 0 1-.445.832l-9 6a1 1 0 0 1-1.11 0l-9-6A1 1 0 0 1 2 15V9z"/></symbol><symbol id="close-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/></symbol><symbol id="menu-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z"/></symbol></defs></svg></head><body data-theme="dark"><div class="sidebar-container"><div class="sidebar" id="sidebar"><div class="sidebar-items-container"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="lib_model.module_js.html">lib/model.js</a></div><div class="sidebar-section-children"><a href="lib_modelview.module_js.html">lib/modelview.js</a></div><div class="sidebar-section-children"><a href="lib_visualizer.module_js.html">lib/visualizer.js</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="lib_model.module_js-AtomImage.html">AtomImage</a></div><div class="sidebar-section-children"><a href="lib_model.module_js-BondImage.html">BondImage</a></div><div class="sidebar-section-children"><a href="lib_model.module_js-Model.html">Model</a></div><div class="sidebar-section-children"><a href="lib_modelview.module_js-ModelView.html">ModelView</a></div><div class="sidebar-section-children"><a href="lib_visualizer.module_js-CrystVis.html">CrystVis</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-tutorials"><div>Tutorials</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="tutorial-Events.html">Events</a></div><div class="sidebar-section-children"><a href="tutorial-Queries.html">Queries</a></div><div class="sidebar-section-children"><a href="tutorial-ThreejsMigration.html">ThreejsMigration</a></div></div></div></div></div><div class="navbar-container" id="VuAckcnZhf"><nav class="navbar"><div class="navbar-left-items"></div><div class="navbar-right-items"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#light-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div><nav></nav></nav></div><div class="toc-container"><div class="toc-content"><span class="bold">On this page</span><div id="eed4d2a0bfd64539bb9df78095dec881"></div></div></div><div class="body-wrapper"><div class="main-content"><div class="main-wrapper"><section class="readme"><article><h1>crystvis-js</h1><p>A <a href="https://threejs.org/">Three.js</a> based crystallographic visualisation tool. It reads multiple file formats and renders them with WebGL to a <code>canvas</code> element, allowing the user to interact with them.</p><blockquote><p><strong>Note:</strong> Version 0.6.0 includes a major update from Three.js 0.137 to 0.178. See <a href="docs-tutorials/ThreejsMigration.md">Three.js Migration Notes</a> and <a href="CHANGELOG.md">CHANGELOG</a> for details.</p></blockquote><p>A few of the key functionality:</p><ul><li>visualize popular file formats as ball-and-stick structures, easily embedded within a webpage, with orbit mouse control for rotation and zooming;</li><li>interactive visualisation responsive to user clicks via customizable callbacks;</li><li>high definition text labels;</li><li>advanced searching and selection functions to interact with specific subset of atoms (select by proximity, bonding, species and more);</li><li>smart visualisation of molecular crystal: reconstruct full molecules across the periodic boundary;</li><li>compute and display isosurfaces from volumetric data;</li><li>visualize tensor data as ellipsoids centred on atoms.</li></ul><h3>Supported formats</h3><p>The currently supported file formats are the following:</p><ul><li><strong>CIF</strong>, using <a href="https://github.com/CCP-NC/crystcif-parse">crystcif-parse</a>;</li><li><strong>XYZ</strong>, specifically the Extended XYZ such as the one written by the <a href="https://wiki.fysik.dtu.dk/ase/">Atomic Simulation Environment</a>;</li><li><strong>CELL</strong>, input file supported by the DFT package <a href="http://www.castep.org/">CASTEP</a>;</li><li><strong>Magres</strong>, output file format for simulated NMR parameters used by CASTEP and Quantum Espresso and developed by the <a href="https://www.ccpnc.ac.uk/">CCP for NMR Crystallography</a>.</li></ul><h3>Getting started</h3><p>In order to install <code>crystvis-js</code>, simply use the Node Package Manager:</p><pre class="prettyprint source lang-bash"><code>npm install crystvis-js --save
4
- </code></pre><p>You can then create a visualizer for your webpage by simply importing and instantiating it:</p><pre class="prettyprint source lang-js"><code>import CrystVis from 'crystvis-js';
5
-
6
- const visualizer = new CrystVis('#target-id', 800, 600)
7
- </code></pre><p>will create an 800x600 canvas with the visualizer inside the element specified by the given selector. To load a model, simply load the contents of your file as a text string and then pass them to the visualizer's <code>loadModels</code> method:</p><pre class="prettyprint source lang-js"><code>var loaded = visualizer.loadModels(contents);
8
- console.log('Models loaded: ', loaded);
9
- // loaded is an object: keys are model names, values are 0 (success) or an error string
10
- var modelName = Object.keys(loaded)[0];
11
- if (loaded[modelName] !== 0) {
12
- console.error('Failed to load model:', loaded[modelName]);
13
- } else {
14
- visualizer.displayModel(modelName);
15
- }
16
- </code></pre><h3>API highlights</h3><p>Full JSDoc documentation is available at <a href="https://ccp-nc.github.io/crystvis-js/">ccp-nc.github.io/crystvis-js</a>.</p><h4>Camera state — save, restore and react to view changes</h4><pre class="prettyprint source lang-js"><code>// Snapshot the current camera (position, target, zoom) — plain JSON-serialisable object
17
- const snap = visualizer.getCameraState();
18
- // { position: {x,y,z}, target: {x,y,z}, zoom: 1 }
19
-
20
- // Restore a previously saved snapshot
21
- visualizer.setCameraState(snap);
22
-
23
- // React to every rotate/pan/zoom (returns an unsubscribe function)
24
- const unsub = visualizer.onCameraChange(state => {
25
- console.log('Camera moved:', state);
26
- });
27
- unsub(); // stop listening
28
- </code></pre><h4>Lifecycle events — react to model and display changes</h4><pre class="prettyprint source lang-js"><code>// Fired whenever models are loaded, deleted, or all cleared
29
- const unsubList = visualizer.onModelListChange(names => {
30
- console.log('Loaded models:', names);
31
- });
32
-
33
- // Fired whenever displayModel() completes; receives model name or null
34
- const unsubDisplay = visualizer.onDisplayChange(name => {
35
- console.log('Now displaying:', name);
36
- });
37
-
38
- // Remove all loaded models in one atomic operation
39
- visualizer.unloadAll();
40
- </code></pre><h4>Model metadata — access source and parameters after loading</h4><pre class="prettyprint source lang-js"><code>// Retrieve the raw file text and extension originally passed to loadModels()
41
- const src = visualizer.getModelSource(modelName);
42
- // { text: '...', extension: 'cif' }
43
-
44
- // Retrieve the merged loading parameters (supercell, molecularCrystal, …)
45
- const params = visualizer.getModelParameters(modelName);
46
-
47
- // Retrieve prefix and original structure name
48
- const meta = visualizer.getModelMeta(modelName);
49
- // { prefix: 'cif', originalName: 'struct' }
50
- </code></pre><h4>Selection serialisation — save and reconstruct atom subsets</h4><pre class="prettyprint source lang-js"><code>// Serialise a selection to plain data
51
- const indices = visualizer.selected.toIndices(); // number[]
52
- const labels = visualizer.selected.toLabels(); // string[] (crystLabel per atom)
53
-
54
- // Reconstruct from indices later
55
- visualizer.selected = visualizer.model.viewFromIndices(indices);
56
-
57
- // Reconstruct from labels — resilient to atom-index reordering on reload
58
- visualizer.selected = visualizer.model.viewFromLabels(labels);
59
- </code></pre><h3>Preparing for development</h3><p>If you want to develop for crystvis-js, you should follow these steps:</p><ul><li>fork the repository</li><li>clone the forked repository locally to your system</li><li>install all the required packages, <em>including the development dependencies</em>, with <code>npm install --production=false</code></li></ul><p>You're then ready to develop. In particular you can use:</p><ul><li><code>npm test</code> to run with Mocha the suite of tests found in <code>./test</code></li><li><code>npm start</code> to start a server that includes the in-browser tests from <code>./test/test-html</code> as well as the demo from <code>./demo</code></li><li><code>npm run docs</code> to compile the documents</li><li><code>npm run deploy-docs</code> to compile the documents and then deploy them to the <code>gh-pages</code> branch of your repository</li></ul><h4>Fonts and shaders</h4><p>Some additional steps are necessary when dealing with fonts and shaders. You generally shouldn't worry about these when working with most of the code, but in some special cases it might be necessary to do this.</p><p>Fonts in crystvis-js need to be translated to a bitmap format to be usable. In other words, a regular font format (like a TTF file) must be rendered into a bitmap texture and a table of coordinates designating each letter to then be used in graphical rendering. This operation relies on the library <code>msdf-bmfont-xml</code> and is executed by running the command <code>npm run build-fonts</code>. The original fonts are found in the <code>./fonts</code> folder, and they get rendered to <code>./lib/assets/fonts</code>. This command needs only to be rerun <em>if the TTF files change</em>.</p><p>Shaders are provided as <code>.frag</code> and <code>.vert</code> files. Both shaders and font textures need to baked directly into the JavaScript files in order to be included in the final build. Since ESBuild (the package used to build crystvis-js) has a hard time dealing with them in the final pass, they get pre-baked with an additional step that only needs to be repeated whenever either of them changes. This consists of taking &quot;template&quot; JS files (for shaders it's <code>./lib/shaders/index.in.js</code>, for fonts <code>./lib/assets/fonts/bmpfonts.in.js</code>) and rebuilding them into final files with the assets imported in data URL form. The script to do this is <code>npm run build-resources</code>. This command only needs to be rerun <em>if the fonts were rebuilt, if the shader code was edited, or if any of the two template files was changed</em>.</p></article></section></div></div></div><div class="search-container" id="PkfLWpAbet" style="display:none"><div class="wrapper" id="iCxFxjkHbP"><button class="icon-button search-close-button" id="VjLlGakifb" aria-label="close search"><svg><use xlink:href="#close-icon"></use></svg></button><div class="search-box-c"><svg><use xlink:href="#search-icon"></use></svg> <input type="text" id="vpcKVYIppa" class="search-input" placeholder="Search..." autofocus></div><div class="search-result-c" id="fWwVHRuDuN"><span class="search-result-c-text">Type anything to view search result</span></div></div></div><div class="mobile-menu-icon-container"><button class="icon-button" id="mobile-menu" data-isopen="false" aria-label="menu"><svg><use xlink:href="#menu-icon"></use></svg></button></div><div id="mobile-sidebar" class="mobile-sidebar-container"><div class="mobile-sidebar-wrapper"><div class="mobile-nav-links"></div><div class="mobile-sidebar-items-c"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="lib_model.module_js.html">lib/model.js</a></div><div class="sidebar-section-children"><a href="lib_modelview.module_js.html">lib/modelview.js</a></div><div class="sidebar-section-children"><a href="lib_visualizer.module_js.html">lib/visualizer.js</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="lib_model.module_js-AtomImage.html">AtomImage</a></div><div class="sidebar-section-children"><a href="lib_model.module_js-BondImage.html">BondImage</a></div><div class="sidebar-section-children"><a href="lib_model.module_js-Model.html">Model</a></div><div class="sidebar-section-children"><a href="lib_modelview.module_js-ModelView.html">ModelView</a></div><div class="sidebar-section-children"><a href="lib_visualizer.module_js-CrystVis.html">CrystVis</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-tutorials"><div>Tutorials</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="tutorial-Events.html">Events</a></div><div class="sidebar-section-children"><a href="tutorial-Queries.html">Queries</a></div><div class="sidebar-section-children"><a href="tutorial-ThreejsMigration.html">ThreejsMigration</a></div></div></div><div class="mobile-navbar-actions"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#light-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div></div></div><script type="text/javascript" src="scripts/core.min.js"></script><script src="scripts/search.min.js" defer="defer"></script><script src="scripts/third-party/fuse.js" defer="defer"></script><script type="text/javascript">var tocbotInstance=tocbot.init({tocSelector:"#eed4d2a0bfd64539bb9df78095dec881",contentSelector:".main-content",headingSelector:"h1, h2, h3",hasInnerContainers:!0,scrollContainer:".main-content",headingsOffset:130,onClick:bringLinkToView})</script></body></html>