-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathwells.html
executable file
·303 lines (261 loc) · 13.7 KB
/
wells.html
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Oil and Gas Wells</title>
<style>
html, body, #map-div, #loading {
margin: 0;
padding: 0;
height: 100%;
background-color: white;
}
#layers {
padding: 5px;
position: absolute;
top: 10px;
right: 10px;
background-color: white;
}
</style>
<link rel="stylesheet" type="text/css" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" type="text/css" href="https://explorables.cmucreatelab.org/data-visualization-tools/css/defaultUI.css" />
</head>
<body>
<div id="loading"></div>
<div id="map-div"></div>
<div id="time-slider-controls"></div>
<div id="layers">Source: Mark Egge, FracTracker Alliance<br /></div>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3.24&key=AIzaSyCLQO-R8kYsKcyHki5SQ3B6mxxYoA1U2hY"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script type="text/javascript" src="https://explorables.cmucreatelab.org/data-visualization-tools/js/CanvasLayer.js"></script>
<script type="text/javascript" src="https://explorables.cmucreatelab.org/data-visualization-tools/js/TimeSlider.js"></script>
<script type="text/javascript">
// draw "loading" pill wheel
for(var i=0, html; i<12; i++) html += "<rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#00b2ff' transform='rotate(" + i*30 + " 50 50) translate(0 -30)'><animate attributeName='opacity' from='1' to='0' dur='1s' begin='" + (i+1)/12 + "s' repeatCount='indefinite'/></rect>";
document.getElementById('loading').innerHTML = '<svg style="position: absolute; top: 50%; left: 50%;" width="120px" height="120px" viewBox="0 0 100 100">' + html + '</svg>';
/**
* Define global variables and utility functions
*/
var map;
var canvasLayer;
var timeSlider;
var gl;
var mapMatrix = new Float32Array(16);
/* dataset parameters:
{
name: 'dataset-name', // required
url: 'dataset/url', // required
rgba: [1.0, 1.0, 0.0, 1.0],
enabled: true,
data: null,
points: 0,
program: null
} */
var datasets = [
{
name: 'combined-2018-dates-filled',
url: 'data/data.bin'
},
{
name: 'combined-2018-raw',
url: 'data/data-plain.bin',
enabled: false
}
];
/**
* Given DOM reference to the vertex shader source and the fragement shader source,
* returns a compiled WebGL program. With error checking.
* @type {String}, {String}
*/
function createProgram(vertexSource, fragmentSource) {
// create vertex shader for points
var vertexSrc = document.getElementById(vertexSource).text; // assign text of source code for vertex-sharder
var vertexShader = gl.createShader(gl.VERTEX_SHADER); // create shader object
gl.shaderSource(vertexShader, vertexSrc); // pass source code to new shader object
gl.compileShader(vertexShader); // compile shader object
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) // verify that shader compiled correctly
console.log(gl.getShaderInfoLog(vertexShader));
// create fragment shader for points
var fragmentSrc = document.getElementById(fragmentSource).text;
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentSrc);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS))
console.log(gl.getShaderInfoLog(fragmentShader));
// link point shaders to create our program
program = gl.createProgram(); // create new program object
gl.attachShader(program, vertexShader); // attach shaders to program object
gl.attachShader(program, fragmentShader);
gl.linkProgram(program); // link shaders
if (!gl.getProgramParameter(program, gl.LINK_STATUS))
console.log(gl.getProgramInfoLog(program));
return program;
}
function loadData(obj) {
var xhr = new XMLHttpRequest();
xhr.open('GET', obj.url);
xhr.responseType = 'arraybuffer';
xhr.onload = function() {
obj.data = new Float32Array(this.response);
obj.dataLoaded = true;
initializeWebGL(obj);
if(obj.enabled != false) document.getElementById('loading').style.display = 'none';
}
xhr.send();
}
/**
* Called after data loaded into object.data. Loads data into a WebGL buffer
*/
function initializeWebGL(obj) {
obj.arrayBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, obj.arrayBuffer);
gl.bufferData(gl.ARRAY_BUFFER, obj.data, gl.STATIC_DRAW);
obj.attributeLocation = gl.getAttribLocation(obj.program, 'a_worldCoord');
obj.timeLocation = gl.getAttribLocation(obj.program, "a_time");
obj.u_ColorLocation = gl.getUniformLocation(obj.program, "u_Color");
obj.matrixLocation = gl.getUniformLocation(obj.program, 'u_mapMatrix');
obj.sliderLocation = gl.getUniformLocation(obj.program, 'u_sliderTime');
obj.count = obj.data.length / 3; // lat, lon, time
if(obj.enabled == null)
obj.enabled = true;
return obj;
}
/** Translate X and Y values to current canvas scale */
function resize() {
console.log('resize handler');
var w = gl.canvas.width;
var h = gl.canvas.height;
gl.viewport(0, 0, w, h);
var scale = canvasLayer.getMapScale();
var t = canvasLayer.getMapTranslation();
mapMatrix.set([ 2 * scale / w, 0, 0, 0,
0, scale * (-2/h), 0, 0,
0, 0, 0, 0,
-1 + (2* t.x * scale)/w, 1 + (-2 * t.y * scale)/h, 0, 1]);
}
/**
* Called by CanvasLayer (controlled, in turn, by TimeSlider).
* Link WebGL program to buffer data, update uniforms, and call draw WebGL function
*/
function drawPoints() {
for(var i = 0; i < datasets.length; i++) {
obj = datasets[i];
if(obj.enabled) {
gl.useProgram(obj.program)
gl.bindBuffer(gl.ARRAY_BUFFER, obj.arrayBuffer);
// enable the 'worldCoord' attribute in the shader to receive buffer
gl.enableVertexAttribArray(obj.attributeLocation);
gl.vertexAttribPointer(obj.attributeLocation, 2, gl.FLOAT, false, 12, 0); // tell webgl how buffer is laid out (lat, lon, time--4 bytes each)
// get the time values out of the buffer
gl.enableVertexAttribArray(obj.timeLocation);
gl.vertexAttribPointer(obj.timeLocation, 1, gl.FLOAT, false, 12, 8); // 8 byte offset
// set uniform values
gl.uniform4f(obj.u_ColorLocation, obj.rgba[0], obj.rgba[1], obj.rgba[2], obj.rgba[3]);
gl.uniformMatrix4fv(obj.matrixLocation, false, mapMatrix);
gl.uniform1f(obj.sliderLocation, timeSlider.getCurrentTime() / 1000.0); // we expect our datasets to have unix timestamps
// draw!
gl.drawArrays(gl.POINTS, 0, obj.count);
timeSlider.animate();
}
}
}
/**
* Initialize WebGL. Called when DOM ready
*/
function init() {
// initialize Google Map
var mapOptions = {
zoom: 5,
center: new google.maps.LatLng(39.3, -95.8),
mapTypeControl: true
};
var styledMapType = new google.maps.StyledMapType(
[{"featureType":"all","elementType":"labels.text.fill","stylers":[{"saturation":36},{"color":"#000000"},{"lightness":40}]},{"featureType":"all","elementType":"labels.text.stroke","stylers":[{"visibility":"on"},{"color":"#000000"},{"lightness":16}]},{"featureType":"all","elementType":"labels.icon","stylers":[{"visibility":"off"}]},{"featureType":"administrative","elementType":"geometry.fill","stylers":[{"color":"#000000"},{"lightness":20}]},{"featureType":"administrative","elementType":"geometry.stroke","stylers":[{"color":"#000000"},{"lightness":17},{"weight":1.2}]},{"featureType":"landscape","elementType":"geometry","stylers":[{"color":"#000000"},{"lightness":20}]},{"featureType":"poi","elementType":"geometry","stylers":[{"color":"#000000"},{"lightness":21}]},{"featureType":"road.highway","elementType":"geometry.fill","stylers":[{"color":"#000000"},{"lightness":17}]},{"featureType":"road.highway","elementType":"geometry.stroke","stylers":[{"color":"#000000"},{"lightness":29},{"weight":0.2}]},{"featureType":"road.arterial","elementType":"geometry","stylers":[{"color":"#000000"},{"lightness":18}]},{"featureType":"road.local","elementType":"geometry","stylers":[{"color":"#000000"},{"lightness":16}]},{"featureType":"transit","elementType":"geometry","stylers":[{"color":"#000000"},{"lightness":19}]},{"featureType":"water","elementType":"geometry","stylers":[{"color":"#000000"},{"lightness":17}]}]);
var mapDiv = document.getElementById('map-div');
map = new google.maps.Map(mapDiv, mapOptions);
map.addListener('bounds_changed', resize, false);
map.mapTypes.set('styled_map', styledMapType);
map.setMapTypeId('styled_map');
// initialize the canvas layer
var canvasLayerOptions = {
map: map,
resizeHandler: resize,
animate: true,
updateHandler: drawPoints
};
canvasLayer = new CanvasLayer(canvasLayerOptions); // create a new canvas
// initialize the TimeSlider
var timeSliderOptions = {
startTime: new Date(1880,00,01).getTime(), // JavaScript counts months from zero. Date constructor defaults to local time
endTime: new Date(2018,03,15).getTime(),
dwellAnimationTime: 2 * 1000,
increment: 120*24*60*60*1000,
formatCurrentTime: function(date) { // Define time label
var month = date.getMonth() + 1, day = date.getDate();
return date.getFullYear() + '-' + (month < 10 ? '0' + month : month) + '-' + (day < 10 ? '0' + day : day);
},
animationRate: {
fast: 20,
medium: 40,
slow: 80
}
};
timeSlider = new TimeSlider(timeSliderOptions);
// initialize WebGL
gl = canvasLayer.canvas.getContext('experimental-webgl'); // initialize WebGL
if(gl == null) {
document.body.innerHTML = 'Error initializing WebGL. Check that you are using a supported browser and that hardware acceleration is enabled.';
return;
}
gl.enable( gl.BLEND );
gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); // explore alpha blending modes at: http://delphic.me.uk/webglalpha.html
//gl.blendFunc( gl.ONE_MINUS_CONSTANT_COLOR, gl.ONE_MINUS_SRC_ALPHA );
// setup our datasets
for (var i = 0; i < datasets.length; i++) {
datasets[i].program = createProgram('point-vertex-shader', 'point-fragment-shader');
if(datasets[i].rgba == null) // if no color is specified, grab one from our colorRamp
datasets[i].rgba = new Array([0.89, 0.05, 0.005, 1.0], [0.22, 0.49, 0.72, 1.0], [0.3, 0.69, 0.29, 1.0], [0.6, 0.31, 0.64, 1.0], [1., 0.5, 0, 1.0], [1., 1., 0.2, 1.0], [0.65, 0.34, 0.16, 1.0], [0.97, 0.51, 0.75, 1.0])[i%8];
loadData(datasets[i]); // load data asychronously
// add layer html
var checked = (datasets[i].enabled != null && datasets[i].enabled == false) ? '' : ' checked';
var html = '<label><input type="checkbox" name="' + i + '"' + checked + '/>' + datasets[i].name + '</label><br />';
document.getElementById('layers').innerHTML += html;
}
$(':checkbox').change(function() {
id = $(this).attr('name');
datasets[id].enabled = $(this).is(":checked");
gl.clear(gl.COLOR_BUFFER_BIT);
});
}
document.addEventListener('DOMContentLoaded', init, false);
</script>
<!-- Create WebGL Shaders -->
<script type="x-shader/x-vertex" id="point-vertex-shader">
attribute vec4 a_worldCoord;
attribute float a_time;
uniform float u_sliderTime;
uniform mat4 u_mapMatrix;
void main() {
// transform world coordinate by matrix uniform variable
if ( a_time > u_sliderTime) {
gl_Position = vec4(-1,-1,-1,-1); // if outside of time window function, do not display
} else {
gl_Position = u_mapMatrix * a_worldCoord;
}
gl_PointSize = 5.0;
}
</script>
<script type="x-shader/x-vertex" id="point-fragment-shader">
precision mediump float;
uniform vec4 u_Color;
void main() {
float dist = distance( vec2(0.5, 0.5), gl_PointCoord);
dist = 1.0 - (dist * 2.0);
dist = max(0.0, dist);
gl_FragColor = u_Color * dist;
}
</script>
</body>
</html>