Related
I have a script that takes more than 5 minutes to execute. So it will be aborted after 5 minutes with the information that the execution time is too long.
Now I am looking for a solution to handle this. In the following example I would like to interrupt when var = i has reached a value of 300 and then continue with i = 301. Is this an option for a workaround? If so, how has the code to be adapted?
var xy = 1100;
for (var = i; i<= xy; i++){
{
do_some_stuff();
}
}
In practice my code is the following....and the loop is starting with for(var i = 3; i <= lastrow +1; i++) lastrow has a value of 1500.
function Create_geodata()
{
var Geodata = getSheetById(1702838837);
var Geojson_Data = getSheetById(1515926044);
var Control_Panel = getSheetById(1102907697);
Geodata.getRange('I4').setValue('Yes');
var Hyperlink_Geodata = Control_Panel.getRange('O18').getValue();
var document_missing_ID = Control_Panel.getRange('O24').getValue();
var Umap_Hyperlink = Control_Panel.getRange('L20').getValue();
var umap_zoom = Control_Panel.getRange('N22').getValue();
var Own_ID_Sort_Setting = Control_Panel.getRange('O30').getValue();
var Own_ID_Sort = Control_Panel.getRange('M32').getValue();
var Threshold_Altitude = Control_Panel.getRange('N28').getValue();
var Automatic_Altitude_Removal = Control_Panel.getRange('O26').getValue();
var Cat_A = Control_Panel.getRange('C36').getValue();
var Cat_B = Control_Panel.getRange('C38').getValue();
var Cat_C = Control_Panel.getRange('C40').getValue();
RESET_Geodata(); //Clear data before proceed
if (Own_ID_Sort_Setting)
{standard_sort_column = Own_ID_Sort}
else
{standard_sort_column = "name"}
var data = Geojson_Data.getDataRange().getValues();
var col1 = data[0].indexOf(standard_sort_column) + 1;
var col2 = data[0].indexOf('coordinates') + 1;
var col3 = data[0].indexOf('name') + 1;
var col4 = data[0].indexOf('description') + 1;
var col1_Char = columnToLetter(col1); //last row of column where sort-criteria is located
var col2_Char = columnToLetter(col2);
var col3_Char = columnToLetter(col3);
var col4_Char = columnToLetter(col4);
var lastrow_col1 = Geojson_Data.getRange(col1_Char + ':' + col1_Char).getValues();
lastrow_col1 = lastrow_col1.filter(String).length;
var lastrow = Geojson_Data.getLastRow();//last row of complete sheet
var lc = Geojson_Data.getLastColumn(); //last column
var lc_Char = columnToLetter(lc);
var dc = 0;
Geojson_Data.getRange('N1').setValue(col1);
if (!document_missing_ID)
{
for(var t = 2; t <= lastrow; t++)
{
if (Geojson_Data.getRange(t,col1).getValue() == "")
{
Geojson_Data.deleteRow(t);
}
}
}
else
{
for(var t = 2; t <= lastrow; t++)
{
if (Geojson_Data.getRange(t,col1).getValue() == "")
{
dc++;
var formattedNumber = ("000" + dc).slice(-4);
Geojson_Data.getRange(t,col1).setValue('ZZ_' + formattedNumber);
}
}
}
Geojson_Data.getRange('A2:' + lc_Char + lastrow).sort(col1);
Geojson_Data.getRange(col1_Char + 2 + ':' + col1_Char + lastrow).copyTo(Geodata.getRange('A3:A' + lastrow),{contentsOnly: true});
Geojson_Data.getRange(col2_Char + 2 + ':' + col2_Char + lastrow).copyTo(Geodata.getRange('F3:F' + lastrow),{contentsOnly: true});
Geojson_Data.getRange(col3_Char + 2 + ':' + col3_Char + lastrow).copyTo(Geodata.getRange('B3:B' + lastrow),{contentsOnly: true});
Geojson_Data.getRange(col4_Char + 2 + ':' + col4_Char + lastrow).copyTo(Geodata.getRange('D3:D' + lastrow),{contentsOnly: true});
var geodata_sorted = '';
var route_length = 0;
for(var i = 3; i <= lastrow +1; i++)
{
var pr = 0;
var fl = false;
var distance_neighbour_points = 0;
var Ar = Geodata.getRange('F' + i).getValue();
Ar = Ar.split(',');
var Ar_Anz = Ar.length - 1;
for(var b = 0; b <= Ar_Anz; b=b+2)
{
if ((Ar_Anz - b) != 0)
{
var E_Lat = Ar[b];
var E_Lon = Ar[b + 1];
if (fl)
{
var A_Lat = Ar[b - 2];
var A_Lon = Ar[b - 1];
distance_neighbour_points = distVincenty(A_Lat, A_Lon, E_Lat, E_Lon);
if (Automatic_Altitude_Removal && (distance_neighbour_points > Threshold_Altitude))
{
b++;
E_Lat = Ar[b];
E_Lon = Ar[b + 1];
A_Lat = Ar[b - 3];
A_Lon = Ar[b - 2];
}
route_length = route_length + distVincenty(A_Lat, A_Lon, E_Lat, E_Lon);
}
pr++;
fl = true;
}
geodata_sorted = geodata_sorted + E_Lat + ',' + E_Lon;
if ((Ar_Anz - b) < 2)
{
}
else
{
geodata_sorted = geodata_sorted + ',';
}
if ((Ar_Anz - b) < 2)
{
pr = parseInt(pr / 2) * 2 + 1;
var Ay = geodata_sorted.split(',');
var Geo_Mitte_Lon = Ay[pr - 1];
var Geo_Mitte_Lat = Ay[pr];
var googlemaps = 'https://maps.google.com/?q=' + Geo_Mitte_Lat + ',' + Geo_Mitte_Lon;
var umap = 'https://umap.openstreetmap.fr/de' + '/map/' + Umap_Hyperlink + '#' + umap_zoom + '/' + Geo_Mitte_Lat + '/' + Geo_Mitte_Lon;
Geodata.getRange(i, 3).setValue(route_length / 1000);
Geodata.getRange(i, 6).setValue(geodata_sorted);
Geodata.getRange(i, 7).setValue(googlemaps);
Geodata.getRange(i, 8).setValue(umap);
//Verlinkung
if (Hyperlink_Geodata)
{
var displayName1 = Geodata.getRange(i,1).getValue();
var displayName2 = Geodata.getRange(i,2).getValue();
Geodata.getRange(i,1).setFormula('=HYPERLINK(\"' + googlemaps + '\";\"' + displayName1 + '\")');
Geodata.getRange(i,2).setFormula('=HYPERLINK(\"' + umap + '\";\"' + displayName2 + '\")');
}
geodata_sorted = '';
route_length = 0;
}
}
//Set categories Cat_A,B,C...
var description_content = Geodata.getRange(i,4).getValue();
var regExpA = new RegExp('/*' + Cat_A, 'gi');
var regExpB = new RegExp('/*' + Cat_B, 'gi');
var regExpC = new RegExp('/*' + Cat_C, 'gi');
var compareA = regExpA(description_content);
var compareB = regExpB(description_content);
var compareC = regExpC(description_content);
if (compareC == Cat_C) Geodata.getRange(i,5).setValue(Cat_C);
if (compareB == Cat_B) Geodata.getRange(i,5).setValue(Cat_B);
if (compareA == Cat_A) Geodata.getRange(i,5).setValue(Cat_A);
}
SpreadsheetApp.getActiveSpreadsheet().setActiveSheet(Geodata);
Geodata.getRange('I4').setValue('No');
}
I am working on the canvas showing levels according to users below is my code the issue is after clip the image on the first level the next drawing and animations stops working.
The canvas holds a json array which is used to draw the levels Class levels
holds the method to deay static shapes and functions starting with animate uses animation frames to animate line or circles.
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
</head>
<body>
<canvas id="levelchart" data-levels="[{"text":"Mark","dotcolor":"#28912e","linecolor":"#28912e","current":"0","completed":"1","image":"http:\/\/nessgoods.com\/timthumb.php?src=http:\/\/www.nessgoods.com\/upload\/users\/3\/pills_311869.jpg&q=100"},{"text":5,"dotcolor":"#28912e","linecolor":"#28912e","current":"0","pending":"0","completed":"1"},{"text":25,"dotcolor":"#28912e","linecolor":"#28912e","current":"0","pending":"0","completed":"1"},{"text":125,"dotcolor":"#28912e","linecolor":"#28912e","current":"0","pending":"0","completed":"1"},{"text":625,"dotcolor":"#28912e","linecolor":"#28912e","current":"0","pending":"0","completed":"1"},{"text":3125,"dotcolor":"#28912e","linecolor":"#28912e","current":"0","pending":"0","completed":"1"},{"text":15625,"dotcolor":"#3498db","linecolor":"#3498db","current":"1","completed":"1","pending":"3125"},{"text":78125,"dotcolor":"#3498db","linecolor":"#3498db","current":0,"pending":"0","completed":0},{"text":390625,"dotcolor":"#3498db","linecolor":"#3498db","current":0,"pending":"0","completed":0}]" width="1360" height="380"></canvas>
</body>
JS:
<script
src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<script type="text/javascript">
class levels{
constructor(){
var x = 0;
var y = 0;
var height = 0;
var width = 0;
var canvas = 0;
var fill = 0;
var start = 0;
var end = 0;
var lineWidth = 0;
var color = 0;
var gradient = 0;
var lineCap = "square";
var to = 0;
var data = 0;
var counter = 0;
var circleanimate = 0;
var percent=0;
var completed = 0;
var imagee = "";
}
config(){
}
line(){
// console.log(this.end);
this.canvas.beginPath();
this.canvas.moveTo(this.start, this.y);
this.canvas.lineTo(this.end, this.y);
this.canvas.lineWidth = this.lineWidth;
this.canvas.strokeStyle = this.color;
this.canvas.lineCap = this.lineCap
this.canvas.stroke();
};
circle(){
this.canvas.beginPath();
this.canvas.moveTo(this.end, this.y);
this.canvas.arc(this.end, this.y, this.radius, 0, 2 * Math.PI);
this.canvas.fillStyle = this.color;
this.canvas.fill();
this.canvas.closePath();
}
baloon(){
var bheight = (10 - lv.counter + lv.counter * 8 / 100 * canvas.height);
var totheight = canvas.height - (60 + bheight);
var height = totheight + 80 / 100 * bheight;
this.canvas.beginPath();
//console.log("check "+bheight+" "+totheight+" "+height);
var last = (lv.end-30) + (15 / 100 * bheight);
var y = lv.y-50;
this.canvas.moveTo(last + (12 / 100 * bheight), height - (13 / 100 * bheight));
this.canvas.bezierCurveTo(last - (16 / 100 * bheight), y, last - (16 / 100 * bheight), y, last - (16 / 100 * bheight), y);
this.canvas.bezierCurveTo(last - (36 / 100 * bheight), height, last - (36 / 100 * bheight), height, last - (36 / 100 * bheight), height);
this.canvas.arc(last - (18 / 100 * bheight), totheight + (38 / 100 * bheight), (last + (14 / 100 * bheight)) - (last - (28 / 100 * bheight)), 0.75 * Math.PI, 0.25 * Math.PI);
this.canvas.strokeStyle = lv.color;
this.canvas.lineWidth=3;
this.canvas.stroke();
// count++;
console.log(lv.imagee+" as");
if (this.imagee != "") {
var img = new Image();
img.src = this.imagee;
var newcanvas = this.canvas;
img.onload = function (e)
{
newcanvas.beginPath();
newcanvas.moveTo(last - (18 / 100 * bheight), totheight + (38 / 100 * bheight));
newcanvas.arc(last - (18 / 100 * bheight), totheight + (38 / 100 * bheight), (last + (14 / 100 * bheight)) - (last - (28 / 100 * bheight)) - 1, 0, 2 * Math.PI);
newcanvas.strokeStyle = "#fff";
newcanvas.stroke();
newcanvas.clip();
newcanvas.drawImage(img,last - (18 / 100 * bheight)-(1.5/100*canvas.width),totheight + (38 / 100 * bheight)-(1.5/100*canvas.width));
lv.canvas.beginPath();
// lv.image="";
}
}
}
}
function animateCircle() {
if(lv.circleanimate<2.1){
requestAnimationFrame(animateCircle);
lv.canvas.beginPath();
lv.canvas.moveTo(lv.end, lv.y);
lv.canvas.arc(lv.end, lv.y, lv.radius, (lv.circleanimate-0.1) * Math.PI, lv.circleanimate * Math.PI);
lv.canvas.fillStyle = lv.color;
lv.strokeStyle = "none";
lv.canvas.fill();
lv.canvas.closePath();
lv.circleanimate=lv.circleanimate+0.1;
}else{
lv.circleanimate=0;
if (lv.end == 0) {
lv.start = 0;
lv.end = 0;
lv.to = 30;
lv.color = lv.data[0].linecolor;
lv.style = "normal";
if(lv.data[0].hasOwnProperty("image")){
lv.imagee = lv.data[0].image;
}
} else {
lv.style = "bold";
lv.start = lv.end + 10;
var index = lv.counter-1;
if(lv.counter>=8){
index = 8;
}
console.log(index+" c ");
lv.imagee = "";
if(lv.data[index].hasOwnProperty("image")){
var w = 3/100*canvas.width;
lv.imagee = lv.data[index].image+"&w="+w+"&h="+w;
}
lv.color = lv.data[index].linecolor;
lv.percent = (Number(lv.data[index].pending) / Number(lv.data[index].text) * 100);
lv.completed = lv.data[index].completed;
lv.end = lv.start;
var p = (lv.counter * 2)+2;
lv.to = lv.to + ((p / 100) * workarea);
}
animateElipse();
animateLineFill();
}
}
function animateElipse(){
if(lv.circleanimate<2.1){
requestAnimationFrame(animateElipse);
var bheight = (10 - lv.counter + lv.counter * 8 / 100 * canvas.height);
var totheight = canvas.height - (60 + bheight);
var height = totheight + 80 / 100 * bheight;
var last = lv.end-25;
var y = lv.y-48;
lv.canvas.beginPath();
lv.canvas.moveTo(last, y);
lv.canvas.ellipse(last, y, 8, 2, 0,0, lv.circleanimate * Math.PI);
lv.canvas.fillStyle = "#e4e5e7";
lv.canvas.fill();
lv.circleanimate=lv.circleanimate+0.1;
}else{
lv.baloon();
}
}
function animateLineFill(){
if(lv.end<lv.to){
requestAnimationFrame(animateLineFill);
}else if(lv.counter<lv.count){
lv.circleanimate=0;
if (lv.end == 0) {
lv.start = 0;
lv.end = 0;
lv.to = 30;
lv.color = lv.data[0].linecolor;
lv.style = "normal";
} else {
lv.style = "bold";
lv.start = lv.end + 8;
var index = lv.counter;
if(lv.counter>=8){
index = 8;
}
lv.imagee = "";
if(lv.data[index].hasOwnProperty("image")){
var w = 3/100*canvas.width;
lv.imagee = lv.data[index].image+"&w="+w+"&h="+w;
}
lv.color = lv.data[index].linecolor;
lv.end = lv.start;
// var p = (lv.counter+1.9 * 5);
// lv.to = lv.to + ((p / 100) * workarea);
}
animateCircle();
lv.counter++;
}
lv.line();
lv.end++;
}
var lv = new levels();
var canvas = document.querySelector("canvas#levelchart");
/*canvas.width = (98 / 100) * $("div.team_link").width();
canvas.height = (28 / 100) * canvas.width;*/
canvas.width = (98 / 100) * $(window).width();
canvas.height = (28 / 100) * canvas.width;
var c = canvas.getContext('2d');
var workarea = (canvas.width);
var points = workarea / 10;
var start = canvas.width - 10;
var last = 0;
var y = canvas.height - 10;
var cheight = canvas.height;
var data = document.getElementById("levelchart").getAttribute("data-levels");
data = JSON.parse(data);
var i = 0;
var style = "normal";
lv.start = start;
lv.end = last;
lv.canvas = c;
lv.color="#000000";
lv.y = y;
lv.start = 50;
lv.end = workarea-50;
lv.lineWidth = 4;
lv.color = "#eee";
lv.lineCap = "round";
lv.line();
lv.end = 0;
lv.radius = 5;
lv.count = data.length;
lv.data = data;
lv.counter = 0;
if (lv.end == 0) {
lv.start = 0;
lv.end = 0;
lv.to = 30;
lv.color = lv.data[0].linecolor;
lv.style = "normal";
}
animateLineFill();
</script>
In image.load function we have to call .save() on canvas and after clip() we have call the .restore() function as defined in below code.
img.onload = function (e)
{
newcanvas.save();
newcanvas.beginPath();
newcanvas.moveTo(last - (18 / 100 * bheight), totheight + (38 / 100 * bheight));
newcanvas.arc(last - (18 / 100 * bheight), totheight + (38 / 100 * bheight), (last + (14 / 100 * bheight)) - (last - (28 / 100 * bheight)) - 1, 0, 2 * Math.PI);
newcanvas.strokeStyle = "#fff";
newcanvas.stroke();
newcanvas.clip();
newcanvas.drawImage(img,last - (18 / 100 * bheight)-(1.5/100*canvas.width),totheight + (38 / 100 * bheight)-(1.5/100*canvas.width));
newcanvas.restore();
// lv.image="";
}
I would like to create an web based guestbook for an 84" multi-touch device. I know how to create a canvas which allows a user to draw, but I wonder if the same is possible for multiple users? I have found some information on html5 multi-touch input, but all of it is related to gestures.
Since the surface is large enough and the device supports it, ideally I would like for several users to draw something onto the canvas simultaneously.
Here is whole program. There is no nothing to allow multiple touch inputs.
You only need to access event.changedTouches
Navigate with mobile device and test demo.
I made also button click detection example (HUB BUTTON).
Source: https://github.com/zlatnaspirala/multi-touch-canvas-handler/blob/master/index.html
function MOBILE_CONTROL () {
this.X = null;
this.Y = null;
this.LAST_X_POSITION = null;
this.LAST_Y_POSITION = null;
this.MULTI_TOUCH = 'NO';
this.MULTI_TOUCH_X1 = null;
this.MULTI_TOUCH_X2 = null;
this.MULTI_TOUCH_X3 = null;
this.MULTI_TOUCH_X4 = null;
this.MULTI_TOUCH_X5 = null;
this.MULTI_TOUCH_Y1 = null;
this.MULTI_TOUCH_Y2 = null;
this.MULTI_TOUCH_Y3 = null;
this.MULTI_TOUCH_Y4 = null;
this.MULTI_TOUCH_Y5 = null;
this.MULTI_TOUCH_X6 = null;
this.MULTI_TOUCH_X7 = null;
this.MULTI_TOUCH_X8 = null;
this.MULTI_TOUCH_X9 = null;
this.MULTI_TOUCH_X10 = null;
this.MULTI_TOUCH_Y6 = null;
this.MULTI_TOUCH_Y7 = null;
this.MULTI_TOUCH_Y8 = null;
this.MULTI_TOUCH_Y9 = null;
this.MULTI_TOUCH_Y10 = null;
this.MULTI_TOUCH_INDEX = 1;
this.SCREEN = [window.innerWidth , window.innerHeight];
this.SCREEN.W = this.SCREEN[0];
this.SCREEN.H = this.SCREEN[1];
//Application general
this.AUTOR = "Nikola Lukic";
this.APPLICATION_NAME = "TestApplication";
this.SET_APPLICATION_NAME = function (value) {
if (typeof value != 'string')
throw 'APPLICATION_NAME must be a string!';
if (value.length < 2 || value.length > 20)
throw 'APPLICATION_NAME must be 2-20 characters long!';
this.APPLICATION_NAME = value;
};
this.APP = function(){/*construct*/};
this.APP.BODY = document.getElementsByTagName('body')[0];
this.APP.BODY.SET_STYLE = function (string) {this.style = string;}
this.APP.BODY.SET_BACKGROUND_COLOR = function (color) {this.style.backgroundColor = color;}
this.APP.BODY.SET_COLOR = function (color) {this.style.Color = color;}
this.APP.BODY.ADD_DIV = function (id , style , innerHTML) {
var n = document.createElement('div');
var divIdName = id;
n.setAttribute('id',divIdName);
n.setAttribute('style',style);
n.innerHTML = innerHTML;
this.appendChild(n);
};
this.APP.BODY.ADD_2DCANVAS = function (id,width_,height_) {
var n = document.createElement('canvas');
var divIdName = id;
n.setAttribute('id',divIdName);
n.setAttribute('width',width_);
n.setAttribute('height',height_);
//n.innerHTML = 'Element is here';
this.appendChild(n);
};
console.log('<MOBILE_CONTROL JavaScript class>');
console.log('status:MOBILE_CONTROL FINISH LOADING');
console.log('EASY_IMPLEMENTATION!');
}
function CANVAS_DRAW() {
var run = true;
var timer = null;
window.addEventListener('touchstart', MDPORT, false);
function MDPORT(){
if (run) {
clearInterval(timer);
run = false;
} else {
timer = setInterval(makeHarmonograph, 1);
run = true;
}
}
var A1 = 200, f1 = 2, p1 = 1/16, d1 = 0.02;
var A2 = 10, f2 = 4, p2 = 3 / 2, d2 = 0.0315;
var A3 = 200, f3 = 4, p3 = 13 / 15, d3 = 0.00012;
var A4 = 10, f4 = 4, p4 = 1, d4 = 0.012;
var r = 10, g =10, b = 0;
var UPDOWN = 1,CONTROL_WIDTH = 0;
var ctx = document.getElementById("canvas").getContext("2d");
setInterval(randomColor, 5000);
timer = setInterval(makeHarmonograph, 1);
function randomColor() {
r = Math.floor(Math.random() * 256);
g = Math.floor(Math.random() * 256);
b = Math.floor(Math.random() * 256);
}
function makeHarmonograph() {
f1 = (f1 / 10) % 10;
f2 = (f2 / 40) % 10;
f3 = (f3 + Math.random() / 80) % 10;
f4 = (f4 + Math.random() / 411) % 10;
p1 += 0.5 % (Math.PI*2)
drawHarmonograph();
}
function drawHarmonograph() {
ctx.clearRect(0, 0, 850, 450);
ctx.save();
ctx.fillStyle = "#000000";
ctx.strokeStyle = "rgb(" + r + "," + g + "," + b + ")";
ctx.fillRect(0, 0, 1100, 400);
ctx.translate(511, 0);
ctx.rotate(1.57);
///////////
// Draw guides
ctx.strokeStyle = '#09f';
ctx.lineWidth = A1 ;
ctx.translate(111, 1);
ctx.rotate(0.01);
if (CONTROL_WIDTH == 0) { UPDOWN=UPDOWN+1;}
if (UPDOWN>51){CONTROL_WIDTH=1; }
if (CONTROL_WIDTH == 0) { UPDOWN=UPDOWN-0.1;}
if (UPDOWN<1){CONTROL_WIDTH=0; }
// Set line styles
ctx.strokeStyle = '#099909';
ctx.lineWidth = UPDOWN;
// check input
ctx.miterLimit = UPDOWN;
// Draw lines
ctx.beginPath();
ctx.moveTo(111,100);
for (i=0;i<121;i++){
var dy = i%2==0 ? 25 : -25 ;
ctx.lineTo(Math.pow(i,1.5)*2,75+dy);
}
ctx.stroke();
return false;
ctx.translate(444, 333);
ctx.fillStyle='lime';
ctx.font="30px Arial";
ctx.fillText("Overlapping harmonics with JavaScript, wait secund.",5,25);
ctx.stroke();
}
}
function CANVAS_DRAW_1(){
var run = true;
var timer = null;
timer = setInterval(makeHarmonograph, 1);
run = true;
var A1 = 200, f1 = 2, p1 = 1/16, d1 = 0.02;
var A2 = 10, f2 = 4, p2 = 3 / 2, d2 = 0.0315;
var A3 = 200, f3 = 4, p3 = 13 / 15, d3 = 0.00012;
var A4 = 10, f4 = 4, p4 = 1, d4 = 0.012;
var r = 10, g =10, b = 0;
var UPDOWN = 1,CONTROL_WIDTH = 0;
var ctx = document.getElementById("canvas_1").getContext("2d");
setInterval(randomColor, 5000);
timer = setInterval(makeHarmonograph, 1);
function randomColor() {
r = Math.floor(Math.random() * 256);
g = Math.floor(Math.random() * 256);
b = Math.floor(Math.random() * 256);
}
function makeHarmonograph() {
f1 = (f1 / 10) % 10;
f2 = (f2 / 40) % 10;
f3 = (f3 + Math.random() / 80) % 10;
f4 = (f4 + Math.random() / 411) % 10;
p1 += 0.5 % (Math.PI*2)
drawHarmonograph();
}
function drawHarmonograph() {
ctx.clearRect(0, 0, 850, 450);
ctx.save();
ctx.fillStyle = "#000000";
ctx.strokeStyle = "rgb(" + r + "," + g + "," + b + ")";
ctx.fillRect(0, 0, 800, 400);
ctx.translate(0, 250);
ctx.beginPath();
if (A1 > 100) {}
for (var t = 0; t < 100; t+=0.1) {
var x = A1 * Math.sin(f1 * t + Math.PI * p1) * Math.exp(-d1 * t) + A2 * Math.sin(f2 * t + Math.PI * p2) * Math.exp(-d2 * t);
var y = A3 * Math.sin(f3 * t + Math.PI * p1) * Math.exp(-d3 * t) + A4 * Math.sin(f4 * t + Math.PI * p4) * Math.exp(-d4 * t);
//ctx.lineTo(x*x, y/x);
ctx.lineTo(x*x+1, y+1/x);
}
ctx.stroke();
ctx.translate(A1, 0);
ctx.rotate(1.57);
ctx.beginPath();
for (var t = 0; t < 100; t+=0.1) {
var x = A1 * A3* Math.sin(f1 * t + Math.PI * p1) * Math.exp(-d1 * t) + A2 * Math.sin(f2 * t + Math.PI * p2) * Math.exp(-d2 * t);
var y = A3 * Math.sin(f3 * t + Math.PI * p1) * Math.exp(-d3 * t) + A4 * Math.sin(f4 * t + Math.PI * p4) * Math.exp(-d4 * t);
ctx.lineTo(x*x+1, y+1/x);
}
ctx.stroke();
ctx.restore();
// Draw guides
ctx.strokeStyle = '#09f';
ctx.lineWidth = A1;
if (CONTROL_WIDTH == 0) { UPDOWN=UPDOWN+1;}
if (UPDOWN>51){CONTROL_WIDTH=1; }
if (CONTROL_WIDTH == 0) { UPDOWN=UPDOWN-0.1;}
if (UPDOWN<1){CONTROL_WIDTH=0; }
// Set line styles
ctx.strokeStyle = '#099909';
ctx.lineWidth = UPDOWN;
// check input
ctx.miterLimit = 5;
// Draw lines
ctx.beginPath();
ctx.moveTo(0,100);
for (i=0;i<124;i++){
var dy = i%2==0 ? 25 : -25 ;
ctx.lineTo(Math.pow(i,1.5)*2,75+dy);
}
ctx.stroke();
return false;
ctx.translate(A1, 210);
ctx.fillStyle='lime';
ctx.font="30px Arial";
ctx.fillText("Overlapping harmonics with JavaScript, wait secund.",5,25);
}
}
function CANVAS_DRAW_2(){
var timer = null;
var A1 = 200, f1 = 2, p1 = 1/16, d1 = 0.02;
var A2 = 10, f2 = 4, p2 = 3 / 2, d2 = 0.0315;
var A3 = 200, f3 = 4, p3 = 13 / 15, d3 = 0.00012;
var A4 = 10, f4 = 4, p4 = 1, d4 = 0.012;
var r = 10, g =10, b = 0;
var ctx = document.getElementById("canvas_2").getContext("2d");
setInterval(randomColor, 5000);
timer = setInterval(t, 1);
function randomColor() {
r = Math.floor(Math.random() * 256);
g = Math.floor(Math.random() * 256);
b = Math.floor(Math.random() * 256);
}
function t() {
r1();
}
function r1() {
ctx.clearRect(0, 0, CONTROL.SCREEN.W, CONTROL.SCREEN.H);
ctx.save();
ctx.strokeStyle = "rgb(" + r + "," + g + "," + b + ")";
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, CONTROL.SCREEN.W, CONTROL.SCREEN.H);
ctx.beginPath();
var x = CONTROL.X;
var y = CONTROL.Y;
ctx.fillStyle = "rgb(" + r + "," + g + "," + b + ")";
ctx.fillRect(x, y-400, 1, 2500);
ctx.fillRect(x-400, y, 2500, 1);
ctx.fillText(" ( targetX:" + CONTROL.X + " ( targetY: "+ CONTROL.Y + " ) ",x,y);
ctx.fillStyle = "#00FF00";
ctx.font="10px Arial";
ctx.fillText(" JavaScript ",x- CONTROL.SCREEN.W/3,y - CONTROL.SCREEN.H/3.4);
ctx.fillText(" welcome here , canvas example with MOBILE_TOUCH() ",x - CONTROL.SCREEN.W/3,y - CONTROL.SCREEN.H/3.2);
ctx.fillText(" no css files need, pure js ",x - CONTROL.SCREEN.W/3,y - CONTROL.SCREEN.H/3);
if (CONTROL.X > CONTROL.SCREEN.W/2.2 && CONTROL.X < CONTROL.SCREEN.W/2.2 + 300 && CONTROL.Y > CONTROL.SCREEN.H/2.2 && CONTROL.Y < CONTROL.SCREEN.H/2.2 + 100) {
ctx.strokeStyle = "lime";
}
else{
ctx.strokeStyle = "red";
}
ctx.strokeRect( CONTROL.SCREEN.W/2.2, CONTROL.SCREEN.H/2.2, 300, 100);
ctx.fillText(" HUB DETECT ", CONTROL.SCREEN.W/2, CONTROL.SCREEN.H/2);
if (CONTROL.MULTI_TOUCH_X1 !== 'undefined'){
ctx.fillRect(CONTROL.MULTI_TOUCH_X1 , CONTROL.MULTI_TOUCH_Y1-400 , 1, 2500);
ctx.fillRect(CONTROL.MULTI_TOUCH_X1 -400 , CONTROL.MULTI_TOUCH_Y1 , 2500, 1);
}
if (CONTROL.MULTI_TOUCH_X2 !== 'undefined'){
ctx.fillRect(CONTROL.MULTI_TOUCH_X2 , CONTROL.MULTI_TOUCH_Y2-400 , 1, 2500);
ctx.fillRect(CONTROL.MULTI_TOUCH_X2 -400 , CONTROL.MULTI_TOUCH_Y2 , 2500, 1);
}
if (CONTROL.MULTI_TOUCH_X3 !== 'undefined'){
ctx.fillRect(CONTROL.MULTI_TOUCH_X3 , CONTROL.MULTI_TOUCH_Y3-400 , 1, 2500);
ctx.fillRect(CONTROL.MULTI_TOUCH_X3 -400 , CONTROL.MULTI_TOUCH_Y3 , 2500, 1);
}
if (CONTROL.MULTI_TOUCH_X4 !== 'undefined'){
ctx.fillRect(CONTROL.MULTI_TOUCH_X4 , CONTROL.MULTI_TOUCH_Y4-400 , 1, 2500);
ctx.fillRect(CONTROL.MULTI_TOUCH_X4 -400 , CONTROL.MULTI_TOUCH_Y4 , 2500, 1);
}
if (CONTROL.MULTI_TOUCH_X5 !== 'undefined'){
ctx.fillRect(CONTROL.MULTI_TOUCH_X5 , CONTROL.MULTI_TOUCH_Y5-400 , 1, 2500);
ctx.fillRect(CONTROL.MULTI_TOUCH_X5 -400 , CONTROL.MULTI_TOUCH_51 , 2500, 1);
}
if (CONTROL.MULTI_TOUCH_X6 !== 'undefined'){
ctx.fillRect(CONTROL.MULTI_TOUCH_X6 , CONTROL.MULTI_TOUCH_Y6-400 , 1, 2500);
ctx.fillRect(CONTROL.MULTI_TOUCH_X6 -400 , CONTROL.MULTI_TOUCH_Y6 , 2500, 1);
}
if (CONTROL.MULTI_TOUCH_X7 !== 'undefined'){
ctx.fillRect(CONTROL.MULTI_TOUCH_X7 , CONTROL.MULTI_TOUCH_Y8-400 , 1, 2500);
ctx.fillRect(CONTROL.MULTI_TOUCH_X7 -400 , CONTROL.MULTI_TOUCH_Y8 , 2500, 1);
}
if (CONTROL.MULTI_TOUCH_X9 !== 'undefined'){
ctx.fillRect(CONTROL.MULTI_TOUCH_X9 , CONTROL.MULTI_TOUCH_Y9-400 , 1, 2500);
ctx.fillRect(CONTROL.MULTI_TOUCH_X9 -400 , CONTROL.MULTI_TOUCH_Y9 , 2500, 1);
}
if (CONTROL.MULTI_TOUCH_X10 !== 'undefined'){
ctx.fillRect(CONTROL.MULTI_TOUCH_X10 , CONTROL.MULTI_TOUCH_Y10-400 , 1, 2500);
ctx.fillRect(CONTROL.MULTI_TOUCH_X10 -400 , CONTROL.MULTI_TOUCH_Y10 , 2500, 1);
}
// Draw lines
ctx.fillStyle='lime';
ctx.font="30px Arial";
ctx.fillText("MOBILE_TOUCH example ",5,25);
}
}
//definition
var CONTROL = new MOBILE_CONTROL();
//CONTROL.APP.BODY.ADD_2DCANVAS("canvas");
//CONTROL.APP.BODY.ADD_2DCANVAS("canvas_1");
CONTROL.APP.BODY.ADD_2DCANVAS("canvas_2",CONTROL.SCREEN.W,CONTROL.SCREEN.H);
CONTROL.APP.BODY.SET_STYLE('margin-left:-10px;padding:0;border:none;');
//CANVAS_DRAW();
//CANVAS_DRAW_1();
CANVAS_DRAW_2();
//<!-- SCREEN.prototype.sayHello = function(){alert ('hello' + "sss" );}; -->
//###################################################################
//EVENTS
//###################################################################
document.addEventListener('touchstart', function(event)
{
if (CONTROL.MULTI_TOUCH == 'NO') {
var touch = event.touches[0];
CONTROL.X = touch.pageX;
CONTROL.Y = touch.pageY;
console.log('TOUCH START AT:(X' + CONTROL.X + '),(' + CONTROL.Y + ')' );
}
else if (CONTROL.MULTI_TOUCH == 'YES') {
var touches_changed = event.changedTouches;
for (var i=0; i<touches_changed.length;i++) {
//CONTROL.MULTI_TOUCH_X1
console.log("multi touch : x" + CONTROL.MULTI_TOUCH_INDEX + ":(" +touches_changed[i].pageX + ")");
switch(CONTROL.MULTI_TOUCH_INDEX)
{
case 1:
CONTROL.MULTI_TOUCH_X1=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y1=touches_changed[i].pageY;
break;
case 2:
CONTROL.MULTI_TOUCH_X2=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y2=touches_changed[i].pageY;
break;
case 3:
CONTROL.MULTI_TOUCH_X3=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y3=touches_changed[i].pageY;
break;
case 4:
CONTROL.MULTI_TOUCH_X4=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y4=touches_changed[i].pageY;
break;
case 5:
CONTROL.MULTI_TOUCH_X5=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y5=touches_changed[i].pageY;
break;
case 6:
CONTROL.MULTI_TOUCH_X6=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y6=touches_changed[i].pageY;
break;
case 7:
CONTROL.MULTI_TOUCH_X7=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y7=touches_changed[i].pageY;
break;
case 8:
CONTROL.MULTI_TOUCH_X8=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y8=touches_changed[i].pageY;
break;
case 9:
CONTROL.MULTI_TOUCH_X9=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y9=touches_changed[i].pageY;
break;
case 10:
CONTROL.MULTI_TOUCH_X10=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y10=touches_changed[i].pageY;
break;
default:
//code to be executed if n is different from case 1 and 2
}
CONTROL.MULTI_TOUCH_INDEX = CONTROL.MULTI_TOUCH_INDEX + 1;
}
}
CONTROL.MULTI_TOUCH = 'YES';
},false);
////////////////////////////////////////////////////////
document.addEventListener('touchmove', function(event)
{
var touch = event.touches[0];
CONTROL.X = touch.pageX;
CONTROL.Y = touch.pageY;
console.log('TOUCH MOVE AT:(X' + CONTROL.X + '),(' + CONTROL.Y + ')' );
//#############
if (CONTROL.MULTI_TOUCH == 'YES') {
var touches_changed = event.changedTouches;
for (var i=0; i<touches_changed.length;i++) {
//CONTROL.MULTI_TOUCH_X1
console.log("multi touch : x" + CONTROL.MULTI_TOUCH_INDEX + ":(" +touches_changed[i].pageX + ")");
switch(i)
{
case 1:
CONTROL.MULTI_TOUCH_X1=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y1=touches_changed[i].pageY;
break;
case 2:
CONTROL.MULTI_TOUCH_X2=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y2=touches_changed[i].pageY;
break;
case 3:
CONTROL.MULTI_TOUCH_X3=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y3=touches_changed[i].pageY;
break;
case 4:
CONTROL.MULTI_TOUCH_X4=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y4=touches_changed[i].pageY;
break;
case 5:
CONTROL.MULTI_TOUCH_X5=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y5=touches_changed[i].pageY;
break;
case 6:
CONTROL.MULTI_TOUCH_X6=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y6=touches_changed[i].pageY;
break;
case 7:
CONTROL.MULTI_TOUCH_X7=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y7=touches_changed[i].pageY;
break;
case 8:
CONTROL.MULTI_TOUCH_X8=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y8=touches_changed[i].pageY;
break;
case 9:
CONTROL.MULTI_TOUCH_X9=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y9=touches_changed[i].pageY;
break;
case 10:
CONTROL.MULTI_TOUCH_X10=touches_changed[i].pageX;
CONTROL.MULTI_TOUCH_Y10=touches_changed[i].pageY;
break;
default:
//code to be executed if n is different from case 1 and 2
}
}}
//#############
event.preventDefault();
},false);
////////////////////////////////////////////////////////
document.addEventListener('touchend', function(event)
{
CONTROL.LAST_X_POSITION = CONTROL.X;
CONTROL.LAST_Y_POSITION = CONTROL.Y;
CONTROL.MULTI_TOUCH = 'NO';
CONTROL.MULTI_TOUCH_INDEX = 1;
CONTROL.MULTI_TOUCH_X1 = null;
CONTROL.MULTI_TOUCH_X2 = null;
CONTROL.MULTI_TOUCH_X3 = null;
CONTROL.MULTI_TOUCH_X4 = null;
CONTROL.MULTI_TOUCH_X5 = null;
CONTROL.MULTI_TOUCH_X6 = null;
CONTROL.MULTI_TOUCH_X7 = null;
CONTROL.MULTI_TOUCH_X8 = null;
CONTROL.MULTI_TOUCH_X9 = null;
CONTROL.MULTI_TOUCH_X10 = null;
CONTROL.MULTI_TOUCH_Y1 = null;
CONTROL.MULTI_TOUCH_Y2 = null;
CONTROL.MULTI_TOUCH_Y3 = null;
CONTROL.MULTI_TOUCH_Y4 = null;
CONTROL.MULTI_TOUCH_Y5 = null;
CONTROL.MULTI_TOUCH_Y6 = null;
CONTROL.MULTI_TOUCH_Y7 = null;
CONTROL.MULTI_TOUCH_Y8 = null;
CONTROL.MULTI_TOUCH_Y9 = null;
CONTROL.MULTI_TOUCH_Y10 = null;
console.log('LAST TOUCH POSITION AT:(X' + CONTROL.X + '),(' + CONTROL.Y + ')' );
},false);
////////////////////////////////////////////////////////
document.addEventListener("touchcancel", function(event)
{
console.log('BREAK - LAST TOUCH POSITION AT:(X' + CONTROL.X + '(,(' + CONTROL.Y + ')' );
}, false);
////////////////////////////////////////////////////////
Maze is generating in a weird fashion. I do not know why, but it generates and breaks down every wall.
here is the code:
public class Main extends Sprite
{
//ARRAYS
private var maze:Array = new Array();
private var pos:Array = new Array();
//INTEGERS
private var num:int = 50;
private var cellX:int = 0;
private var cellY:int = 0;
private var mazeX:int = num;
private var mazeY:int = num;
//POINTS
private var startCell:Point = new Point();
//SPRITES
private var mazeSpriteT:Sprite = new Sprite();
private var mazeSpriteB:Sprite = new Sprite();
private var mazeSpriteL:Sprite = new Sprite();
private var mazeSpriteR:Sprite = new Sprite();
//broken wall
private var brWall:Sprite = new Sprite();
public function Main():void
{
//creating the initial grid, cells and points
setMaze();
//calling function to generate maze
generate(startCell);
}
public function setMaze():void
{
//clearing the screen from all graphical images
mazeSpriteT.graphics.clear();
mazeSpriteB.graphics.clear();
mazeSpriteR.graphics.clear();
mazeSpriteL.graphics.clear();
brWall.graphics.clear();
maze = new Array();
pos = new Array();
for (var i:int = 0; i < 10; i++) {
maze[i] = new Array();
pos[i] = new Array();
for (var j:int = 0; j < 10; j++) {
//maze
maze[i][j] = new Cell;
maze[i][j].visited = false;
//pos
pos[i][j] = new Point(cellX, cellY);
//graphics
mazeSpriteT.graphics.lineStyle(5, 0x000000, 1);
mazeSpriteB.graphics.lineStyle(5, 0x000000, 1);
mazeSpriteR.graphics.lineStyle(5, 0x000000, 1);
mazeSpriteL.graphics.lineStyle(5, 0x000000, 1);
//toplines
addChild(mazeSpriteT);
mazeSpriteT.graphics.moveTo(mazeX, mazeY);
mazeSpriteT.graphics.lineTo(mazeX + num, mazeY);
mazeSpriteT = new Sprite();
//bottomlines
addChild(mazeSpriteB);
mazeSpriteB.graphics.moveTo(mazeX, mazeY + num);
mazeSpriteB.graphics.lineTo(mazeX + num, mazeY + num);
mazeSpriteB = new Sprite();
//rightlines
addChild(mazeSpriteR);
mazeSpriteR.graphics.moveTo(mazeX + num, mazeY);
mazeSpriteR.graphics.lineTo(mazeX + num, mazeY + num);
mazeSpriteR = new Sprite();
//leftlines
addChild(mazeSpriteL);
mazeSpriteL.graphics.moveTo(mazeX, mazeY);
mazeSpriteL.graphics.lineTo(mazeX, mazeY + num);
mazeSpriteB = new Sprite();
cellX += 10;
mazeX += num;
}
cellX = 0;
cellY += 10;
mazeX = num;
mazeY += num;
}
//maze entrance
startCell = pos[0][0];
}
public function generate(cell:Point):void
{
var cx:int = cell.x / 10;
var cy:int = cell.y / 10;
maze[cy][cx].visited = true;
var neighbours:Array = new Array();
fillNeighbours(neighbours, cell);
trace(neighbours.length);
while (neighbours.length > 0) {
var index:int = (Math.random() * neighbours.length);
Math.floor(index);
var arr:Array = neighbours.splice(index, 1);
var pnt:Point = new Point(arr[0].x, arr[0].y);
breakWall(cell, pnt);
generate(pnt);
//trace("index: " + index);
//trace("obx: " + arr[0].x + " oby: " + arr[0].y);
//trace("pnt: " + pnt);
}
}
public function fillNeighbours(neighbours:Array, cell:Point):Array
{
var cx:int = cell.x / 10;
var cy:int = cell.y / 10;
/*for (var i:int = 0; i < maze.length; i++) {
for (var j:int = 0; j < maze[i].length; j++) {
//outerwall parameters
maze[0][j].north = false;
maze[maze.length - 1][j].south = false;
maze[i][maze[i].length-1].east = false;
maze[i][0].west = false;
}
} */
//south neigbours
if (cy < maze.length - 1) {
if (maze[cy + 1][cx].visited == true) {
maze[cy][cx].south = false;
} else {
neighbours.push(pos[cy + 1][cx]);
}
}
if (cy > 0) {
//north neighbours
if (maze[cy - 1][cx].visited == true) {
maze[cy][cx].north = false;
} else {
neighbours.push(pos[cy - 1][cx]);
}
}
if (cx < maze.length - 1) {
//east neighbours
if (maze[cy][cx + 1].visited == true) {
maze[cy][cx].east = false;
} else {
neighbours.push(pos[cy][cx + 1]);
}
}
if (cx > 0) {
//west neighbours
if (maze[cy][cx - 1].visited == true) {
maze[cy][cx].west = false;
} else {
neighbours.push(pos[cy][cx - 1]);
}
}
trace("--");
return(neighbours);
}
public function breakWall(cell:Point, pnt:Point):void
{
var cx:int = cell.x / 10;
var cy:int = cell.y / 10;
var px:int = pnt.x / 10;
var py:int = pnt.y / 10;
brWall.graphics.lineStyle(5, 0xFFFFFF, 1); //white walls
addChild(brWall);
trace(cx, px);
if (cy == py) { //horizontal transition
if (cx > px) { //right to left
brWall.graphics.moveTo((cx * num) + num, (cy * num) + num);
brWall.graphics.lineTo((cx * num) + num, (cy * num) + (num * 2));
} else if (cx < px) { //left to right
brWall.graphics.moveTo((cx * num) + (num * 2), (cy * num) + (num * 2));
brWall.graphics.lineTo((cx * num) + (num * 2), (cy * num) + num);
}
}
if (cx == px) { //vertical transition
if (cy > py) { //down to up
brWall.graphics.moveTo((cx * num) + (num * 2), (cy * num) + num);
brWall.graphics.lineTo((cx * num) + num, (cy * num) + num);
} else if (cy < py){ //up to down
brWall.graphics.moveTo((cx * num) + num, (cy * num) + (num * 2));
brWall.graphics.lineTo((cx * num) + (num * 2), (cy * num) + (num * 2));
}
}
brWall = new Sprite();
}
}
}
I have been praying for help. Be the one to answer my prayers (I will give you five internet dollars).
I'm not too sure I understand completely. You're running a loop that breaks down each wall
while (neighbours.length > 0) {
var index:int = (Math.random() * neighbours.length);
Math.floor(index);
var arr:Array = neighbours.splice(index, 1);
var pnt:Point = new Point(arr[0].x, arr[0].y);
breakWall(cell, pnt);
generate(pnt);
//trace("index: " + index);
//trace("obx: " + arr[0].x + " oby: " + arr[0].y);
//trace("pnt: " + pnt);
}
Just remove breakWall(cell,pnt)?
I took the example of Laplace from "Making image filters with Canvas", but I can not understand the use of Math.min() function in the following lines. Can anyone explain to me how the Laplace?
var weights = [-1,-1,-1,
-1, 8,-1,
-1,-1,-1];
var opaque = true;
var side = Math.round(Math.sqrt(weights.length));
var halfSide = Math.floor(side/2);
var imgd = context.getImageData(0, 0, canvas.width, canvas.height);
var src = imgd.data;
var sw = canvas.width;
var sh = canvas.height;
var w = sw;
var h = sh;
var output = contextNew.createImageData(w, h);
var dst = output.data;
var alphaFac = opaque ? 1 : 0;
for (var y=0; y<h; y++) {
for (var x=0; x<w; x++) {
var sy = y;
var sx = x;
var dstOff = (y*w+x)*4;
var r=0, g=0, b=0, a=0;
for (var cy=0; cy<side; cy++) {
for (var cx=0; cx<side; cx++) {
var scy = Math.min(sh-1, Math.max(0, sy + cy - halfSide));
var scx = Math.min(sw-1, Math.max(0, sx + cx - halfSide));
var srcOff = (scy*sw+scx)*4;
var wt = weights[cy*side+cx];
r += src[srcOff] * wt;
g += src[srcOff+1] * wt;
b += src[srcOff+2] * wt;
a += src[srcOff+3] * wt;
}
}
dst[dstOff] = r;
dst[dstOff+1] = g;
dst[dstOff+2] = b;
dst[dstOff+3] = a + alphaFac*(255-a);
}
}
its algorithm is something like
for y = 0 to imageHeight
for x = 0 to imageWidth
sum = 0
for i = -h to h
for j = -w to w
sum = sum + k(j, i) * f(x – j, y – i)
end for j
end for i
g(x, y) = sum end for x end for y