-
Notifications
You must be signed in to change notification settings - Fork 3
/
cell.js
169 lines (154 loc) · 6.35 KB
/
cell.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import * as THREE from "three";
const TV3 = THREE.Vector3;
/*
* Mixin containing the logic for dealing with the calculation/unit cell.
* Draws cell edges as lines.
* NOTE: `this._cell` is set inside WaveBase.constructor.
*/
export const CellMixin = (superclass) =>
class extends superclass {
constructor(config) {
super(config);
this.drawUnitCell = this.drawUnitCell.bind(this);
}
get cell() {
return this._cell;
}
set cell(s) {
this._cell = s;
}
setCell(s) {
this.cell = s;
}
/**
* Returns an array of vertices in 3D space forming the cell.
* @param cell {Object} unitCell class instance.
* @param zMultiplier {Number} specifies a multiplier to adjust the z coordinates of the cell vertices with.
*/
// eslint-disable-next-line class-methods-use-this
getCellVertices(cell, zMultiplier = 1) {
return [
[0, 0, 0],
[cell.ax, cell.ay, cell.az],
[cell.bx, cell.by, cell.bz],
[cell.ax + cell.bx, cell.ay + cell.by, cell.az + cell.bz],
[cell.cx, cell.cy, cell.cz * zMultiplier],
[cell.cx + cell.ax, cell.cy + cell.ay, cell.cz * zMultiplier + cell.az],
[cell.cx + cell.bx, cell.cy + cell.by, cell.cz * zMultiplier + cell.bz],
[
cell.cx + cell.ax + cell.bx,
cell.cy + cell.ay + cell.by,
cell.cz * zMultiplier + cell.az + cell.bz,
],
];
}
/**
* Returns the cell's center point in 3D space in the form of coordinate array,
* as well as cell height, width, and the maximum between the height and width.
* @param cell {Object} unitCell class instance.
* @returns {{center:Array<Number>, width:Number, height:Number, maxSize:Number}}
*/
getCellViewParams(cell = this.cell) {
let diagonal;
if (this.areNonPeriodicBoundariesPresent) {
const verticesUp = this.getCellVertices(cell, 0.5);
const verticesDown = this.getCellVertices(cell, -0.5);
diagonal = [verticesUp[4], verticesDown[7]];
} else {
const vertices = this.getCellVertices(cell);
diagonal = [vertices[0], vertices[7]];
}
const center = [
(diagonal[0][0] + diagonal[1][0]) / 2,
(diagonal[0][1] + diagonal[1][1]) / 2,
(diagonal[0][2] + diagonal[1][2]) / 2,
];
const width = Math.abs(diagonal[0][1] + diagonal[1][1]);
const height = Math.abs(diagonal[0][2] + diagonal[1][2]);
const maxSize = Math.max(width, height);
return {
center,
width,
height,
maxSize,
};
}
/**
* Returns a LineSegments object representing the cell with given edges.
* @param cell {Object} unitCell class instance.
* @param edges {Array} an array of vertex indices used to form the line segments.
* @param zMultiplier {Number} specifies a multiplier to adjust the z coordinates of the cell vertices with.
* @param lineColor {Number} line segment color
* @returns {LineSegments}
*/
getUnitCellObjectByEdges(
cell,
edges,
zMultiplier = 1,
lineColor = this.settings.defaultColor,
) {
const vertices = this.getCellVertices(cell, zMultiplier);
const points = edges.map(
(edge) => new TV3(vertices[edge][0], vertices[edge][1], vertices[edge][2]),
);
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const lineMaterial = new THREE.LineBasicMaterial({
color: lineColor,
linewidth: this.settings.lineWidth,
});
return new THREE.LineSegments(geometry, lineMaterial);
}
/**
* Returns a LineSegments object representing the full unitCell (with all edges).
*/
getUnitCellObject(cell) {
const edges = [0, 1, 0, 2, 1, 3, 2, 3, 4, 5, 4, 6, 5, 7, 6, 7, 0, 4, 1, 5, 2, 6, 3, 7];
this.unitCellObject = this.getUnitCellObjectByEdges(cell, edges);
this.unitCellObject.name = "Cell";
return this.unitCellObject;
}
/**
* Draw unitCell in canvas. 2 half up/down cells (without top edges) are drawn if boundary conditions are present.
*/
drawUnitCell(cell = this.cell) {
if (this.areNonPeriodicBoundariesPresent) {
const edges = [0, 1, 0, 2, 1, 3, 2, 3, 0, 4, 1, 5, 2, 6, 3, 7];
const cellObjectUp = this.getUnitCellObjectByEdges(cell, edges, 0.5);
const cellObjectDown = this.getUnitCellObjectByEdges(
cell,
edges,
-0.5,
this.settings.colors.gray,
);
this.structureGroup.add(cellObjectDown);
this.structureGroup.add(cellObjectUp);
} else {
const unitCellObject = this.getUnitCellObject(cell);
this.structureGroup.add(unitCellObject);
}
}
/**
* Returns an array of THREE.Plane corresponding to the cell's faces.
*/
getCellPlanes(cell) {
const vertices = this.getCellVertices(cell).map((a) => new THREE.Vector3(...a));
return [
[0, 1, 2],
[0, 1, 4],
[1, 3, 5],
[3, 2, 7],
[0, 2, 4],
[4, 6, 5],
].map((face) => {
const slide1 = new THREE.Vector3().subVectors(vertices[face[0]], vertices[face[1]]);
const slide2 = new THREE.Vector3().subVectors(vertices[face[0]], vertices[face[2]]);
return new THREE.Plane(new THREE.Vector3().crossVectors(slide1, slide2));
});
}
/**
* Return the length of unitCell c vector.
*/
get cVectorLength() {
return new THREE.Vector3(this.cell.cx, this.cell.cy, this.cell.cz).length();
}
};