source: src/openlayers_heatmap/script/canvas_barrier.js@ 9182

Last change on this file since 9182 was 8966, checked in by dennisw, 14 years ago

openlayers_heatmap - toegevoegd, voorbeeld met standaard data

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision
  • Property svn:mime-type set to text/plain
File size: 6.1 KB
Line 
1/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
2 * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
3 * full text of the license. */
4
5/**
6 * CanvasBarrier is a helper class, to execute an operation
7 * on a canvas' pixel data in several web workers. The canvas
8 * is cut into rows and each web worker independently processes
9 * its part. When all web worker are finished, the method
10 * 'callbackDone' is triggered.
11 *
12 * @param {Object} numberOfWorkers - How many web worker should be used?
13 * @param {Object} canvasContext - The canvas' drawing context.
14 * @param {Object} workerScript - Path to the script which contains the web worker code.
15 * @param {Object} callbackDone - Triggered when all web workers are finished
16 * @param {Object} callbackStatus - Optional, triggered on a status update.
17 * @param {Object} parameters - Optional, additional parameters that are passed to each worker.
18 */
19var CanvasBarrier = function(numberOfWorkers, canvasContext, workerScript, callbackDone,
20 callbackStatus, parameters) {
21
22 this.numberOfWorkers = numberOfWorkers;
23 this.callbackDone = callbackDone;
24 this.callbackStatus = callbackStatus;
25 this.canvasContext = canvasContext;
26 this.parameters = parameters;
27
28 this.runningWorkers = 0;
29 this.error = null;
30
31 /**
32 * Start the web workers.
33 */
34 this.start = function() {
35 var canvasWidth = this.canvasContext.canvas.width;
36 var canvasHeight = this.canvasContext.canvas.height;
37
38 this.runningWorkers = this.numberOfWorkers;
39 this.progress = [];
40 this.lastProgress = 0;
41
42 // create a web worker for each row
43 for (var i = 0; i < this.numberOfWorkers; i++) {
44 this.progress.push(0);
45
46 // get the position of this row
47 var x = 0;
48 var y = this.getRowPositionY(i, canvasHeight);
49 var width = canvasWidth;
50 var height = this.getRowPositionY(i+1, canvasHeight) - y;
51
52 // get the pixel data for this row
53 var imageData = this.canvasContext.getImageData(x, y, width, height);
54
55 // now we could use the keyword 'let' for not having to do this cascaded closures:
56 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Working_with_Closures#Creating_closures_in_loops.3a_A_common_mistake
57 var onMessage = this.getOnMessageCallback(i, this.canvasContext, x, y, this);
58 var onError = this.getOnErrorCallback(this);
59
60 // start a web worker
61 var worker = new Worker(workerScript);
62 worker.onmessage = onMessage;
63 worker.onerror = onError;
64
65 var task = {
66 parameters: this.parameters,
67 imageData: imageData
68 }
69
70 worker.postMessage(task);
71 }
72 };
73
74 /**
75 * Returns the y-position for the given row.
76 *
77 * @param {Object} i - Row index
78 * @param {Object} height - The canvas' height
79 * @return {Integer} - Y-Position
80 */
81 this.getRowPositionY = function(i,height) {
82 return Math.floor(height / this.numberOfWorkers * i);
83 };
84
85 /**
86 * Returns a callback function that is used as
87 * onmessage handler for the web worker.
88 *
89 * @param {Object} index - Row index
90 * @param {Object} canvasContext - Canvas context
91 * @param {Object} x - X-Position of the row
92 * @param {Object} y - Y-Position of the row
93 * @param {Object} barrier
94 */
95 this.getOnMessageCallback = function(index, canvasContext, x, y, barrier) {
96 var context = {
97 index: index,
98 canvasContext: canvasContext,
99 x: x,
100 y: y,
101 barrier: barrier
102 };
103
104 return function(event) {
105 if (event.data.status === "progress" && context.barrier.callbackStatus) {
106 context.barrier.reportProgress(context.index, event.data.progress);
107 } else if (event.data.status === "done") {
108 var imageData = event.data.imageData;
109 // directly write the row on the canvas
110 context.canvasContext.putImageData(imageData, context.x, context.y);
111 context.barrier.checkRunningWorkers();
112 }
113 };
114 };
115
116 /**
117 * Returns a callback function that is used as
118 * onerror handler for the web worker.
119 *
120 * @param {Object} barrier
121 */
122 this.getOnErrorCallback = function(barrier) {
123 return function(error) {
124 barrier.error = error;
125 barrier.checkRunningWorkers();
126 };
127 };
128
129 /**
130 * Called from the onmessage and onerror callback. When
131 * all web workers are finished, 'callbackDone' is triggered.
132 */
133 this.checkRunningWorkers = function() {
134 this.runningWorkers--;
135
136 if (this.runningWorkers === 0) {
137 // all workers are finished
138 this.callbackDone({
139 canvas: this.canvas,
140 error: this.error
141 });
142 }
143 };
144
145 /**
146 * Each web worker individually reports its progress. This method
147 * calculates the overall progress and calls 'callbackStatus'.
148 *
149 * @param {Object} index - The row index.
150 * @param {Object} progress - The progress for this row.
151 */
152 this.reportProgress = function(index, progress) {
153 // update the progress for this worker
154 this.progress[index] = progress;
155
156 // then calculate the overall progress of all workers
157 var sum = 0;
158 for (var i = 0; i < this.progress.length; i++) {
159 sum += this.progress[i];
160 }
161 var overallProgress = Math.round(sum / (this.numberOfWorkers * 100) * 100);
162
163 if (overallProgress > this.lastProgress) {
164 this.lastProgress = overallProgress;
165 this.callbackStatus(overallProgress);
166 }
167 };
168};
Note: See TracBrowser for help on using the repository browser.