-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathDataVisualizer.js
More file actions
119 lines (97 loc) · 3.6 KB
/
Copy pathDataVisualizer.js
File metadata and controls
119 lines (97 loc) · 3.6 KB
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
class DataVisualizer {
constructor({
baseMapUrl,
dataMapUrl,
width,
height,
dataDepth,
}) {
if (
!baseMapUrl
|| !dataMapUrl
|| !width
|| !height
|| !dataDepth
) {
throw new Error('missing param');
}
this.baseMapUrl = baseMapUrl;
this.dataMapUrl = dataMapUrl;
this.width = width;
this.height = height;
this.dataDepth = dataDepth;
}
async init() {
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 50, 50);
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var lights = [];
lights[0] = new THREE.PointLight(0xffffff, .5, 0);
lights[1] = new THREE.PointLight(0xffffff, .5, 0);
lights[2] = new THREE.PointLight(0xffffff, .5, 0);
lights[0].position.set(0, 200, 0);
lights[1].position.set(100, 200, 100);
lights[2].position.set(- 100, - 200, - 100);
scene.add(lights[0]);
scene.add(lights[1]);
scene.add(lights[2]);
const imageData = await getImageData(this.dataMapUrl, .25);
function f(x) {
// return Math.log10(x*1000)/10;
return Math.max(0, Math.min(1, Math.exp(x * 2) / 2.2 - 1));
}
function threshold(x, tres = 0.05) {
return x < tres ? undefined : x;
}
// get only red color components since the image is greyscale
const data = imageData.map(
row => row.map(
([r, g, b, a]) => threshold(f((255 - r) / 255), 0.1)
)
);
// create a palette of 10 different materials
const materials = createMaterialPalette(10)
var singleGeometry = new THREE.Geometry();
const dataWidth = data.length;
const dataHeight = !data[0] ? 0 : data[0].length;
for (let j = 0; j < data.length; j++) {
const row = data[j];
for (let i = 0; i < row.length; i++) {
const value = row[i];
if (value !== undefined) {
var box = new THREE.BoxGeometry(1, 1, 1);
var cube = new THREE.Mesh(box);
cube.applyMatrix(new THREE.Matrix4().makeTranslation(.01 + i - row.length / 2, 0.5, .01 + j - data.length / 2));
cube.applyMatrix(new THREE.Matrix4().makeScale(this.width / dataWidth, value * this.dataDepth, this.height / dataHeight));
//cube.updateMatrix();
for ( var k = 0; k < box.faces.length; k++ ) {
box.faces[k].materialIndex = Math.floor(value * (materials.length - 1));
}
singleGeometry.merge(cube.geometry, cube.matrix);
}
}
}
var map = createMap({ width: this.width, height: this.height, url: this.baseMapUrl });
scene.add(map);
var mesh = new THREE.Mesh(singleGeometry, materials);
scene.add(mesh);
// setup mouse controls
const controls = setupControls(camera, renderer);
var animate = function () {
requestAnimationFrame(animate);
// trigger event to update controls
controls.update();
renderer.render(scene, camera);
};
animate();
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
}
}