javascript promises does not work as expected while image combining - javascript

below is my javascript code which i use for combining 64 images to generate a panorama image. but when i load it first time it gives me broken image however at seconds or third time it gives me right image.
In Below combine function do all image combine process,
combinedArray contains all urls of images.
function combine(imgSources, width, height, right, left) {
return Promise.all(imgSources.map(function (url) {
return new Promise(function (resolve) {
let img = new Image();
img.crossOrigin = `anonymous`;
img.src = url;
img.onload = function () {resolve(img);};
});
})).then(function (images) {
let canvas = document.createElement(`canvas`);
canvas.width = width;
canvas.height = height;
// draw images to the canvas
let ctx = canvas.getContext(`2d`);
for (let i = 0; i < imgSources.length; i++) {
ctx.drawImage(images[i], right * i, left * i);
}
// return the resulting image in base64 form
return canvas.toDataURL(`image/jpeg`);
});
}
function generateParonama(angle = 10) {
let url=`https://cdn.yourvrtours.com/000679.fcf5f084b8794573a6789774f9bfcbaf.1122/A4CDD7C7-3F58-435A-9A5B-9522078DE10B/optimized/Point_7537F461-3868-4EFB-9B82-3A1E3CF81955/3/`;
let mainImage;
let allSides = [`f`, `r`, `b`, `l`];
let allImages = [];
let combinedArray = [];
let ind = 0;
// generates array for all 64 images
function genareteArray() {
for (let index = 0; index < allSides.length; index++) {
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
let t = `${url + allSides[index] + j + '_' + i}.jpg`;
combinedArray.push(t);
}
}
}
}
// arrange array at given angle
function reArrangeArray() {
let position = 0 / 22.5;
let array2 = [];
if (position <= 8) {
position = (position + 8) * 4;
array2 = combinedArray.slice(position, 64);
combinedArray.splice(position)
combinedArray = array2.concat(combinedArray)
}
else {
position = (position - 8) * 4;
array2 = combinedArray.slice(0, position);
combinedArray.push(array2)
}
}
genareteArray();
reArrangeArray();
allSides.map((side, i) => {
return new Promise((res) => {
for (let index = 0; index < 4; index++) {
combine(
[
combinedArray[0 + ind],
combinedArray[1 + ind],
combinedArray[2 + ind],
combinedArray[3 + ind],
], 512, 2048, 0, 512)
.then(function (result) {
// result will be a column of 512 box
allImages.push(result);
if (allImages.length > 15) {
combine(allImages, 8192, 2048, 512, 0).then((r) => {
var img = new Image();
img.src = r;
document.body.appendChild(img);
});
}
});
ind = ind + 4;
}
});
});
}
generateParonama(10);
img{
max-width:600px;
}

Can you try this -
function combine(imgSources, width, height, right, left) {
return Promise.all(imgSources.map(function (url) {
return new Promise(function (resolve) {
let img = new Image();
img.crossOrigin = `anonymous`;
img.src = url;
img.onload = function () { resolve(img); };
});
})).then(function (images) {
let canvas = document.createElement(`canvas`);
canvas.width = width;
canvas.height = height;
// draw images to the canvas
let ctx = canvas.getContext(`2d`);
for (let i = 0; i < imgSources.length; i++) {
ctx.drawImage(images[i], right * i, left * i);
}
// return the resulting image in base64 form
return canvas.toDataURL(`image/jpeg`);
});
}
async function generateParonama(angle = 10) {
let url = `https://cdn.yourvrtours.com/000679.fcf5f084b8794573a6789774f9bfcbaf.1122/A4CDD7C7-3F58-435A-9A5B-9522078DE10B/optimized/Point_7537F461-3868-4EFB-9B82-3A1E3CF81955/3/`;
let mainImage;
let allSides = [`f`, `r`, `b`, `l`];
let allImages = [];
let combinedArray = [];
let ind = 0;
// generates array for all 64 images
function genareteArray() {
for (let index = 0; index < allSides.length; index++) {
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
let t = `${url + allSides[index] + j + '_' + i}.jpg`;
combinedArray.push(t);
}
}
}
}
// arrange array at given angle
function reArrangeArray() {
let position = 0 / 22.5;
let array2 = [];
if (position <= 8) {
position = (position + 8) * 4;
array2 = combinedArray.slice(position, 64);
combinedArray.splice(position)
combinedArray = array2.concat(combinedArray)
}
else {
position = (position - 8) * 4;
array2 = combinedArray.slice(0, position);
combinedArray.push(array2)
}
}
genareteArray();
reArrangeArray();
console.log(combinedArray);
for (let i = 0; i < allSides.length; i++) {
const side = allSides[i];
for (let index = 0; index < 4; index++) {
var result = await combine(
[
combinedArray[0 + ind],
combinedArray[1 + ind],
combinedArray[2 + ind],
combinedArray[3 + ind],
], 512, 2048, 0, 512);
// result will be a column of 512 box
allImages.push(result);
if (allImages.length > 15) {
var r = await combine(allImages, 8192, 2048, 512, 0);
var img = new Image();
img.src = r;
document.body.appendChild(img);
}
ind = ind + 4;
}
}
}
generateParonama(10);
It is not the most efficient way of using promises. I only used async-await feature to make sure image components are getting loaded in sequence.
As an example this solution might be made more efficient by using Promise.All API (you can it by altering my code)

Related

A* Algorithm - Javascript: Why does my algorithm not find the shortest path

I am working on visualizing A*. I have a problem where the algorithm finds a path, but it is not the shortest. If I remove the part of the A* function code which is commented as 'tie-breaking', the algorithm finds the shortest path, but it searches the whole grid just like Dijkstra's algorithm, which I don't think A* is supposed to do. These are the pictures of the results with and without tie-breaking:
With Tie-Breaking
Without Tie-Breaking
What is wrong? Here is my A* function:
async a_star_search() {
this.clearSearchNotWalls();
let openSet = [];
let closedSet = [];
let start, end;
let path = [];
this.findNeighbors();
//shapes is a 2d array of squares... a grid
for (let i = 0; i < this.shapes.length; i++) {
for (let j = 0; j < this.shapes[0].length; j++) {
if (this.shapes[i][j].type == "Start") {
start = this.shapes[i][j];
}
if (this.shapes[i][j].type == "End") {
end = this.shapes[i][j];
}
}
}
openSet.push(start);
while (openSet.length > 0) {
let lowestIndex = 0;
//find lowest index
for (let i = 0; i < openSet.length; i++) {
if (openSet[i].F < openSet[lowestIndex].F)
lowestIndex = i;
}
//current node
let current = openSet[lowestIndex];
//if reached the end
if (openSet[lowestIndex] === end) {
path = [];
let temp = current;
path.push(temp);
while (temp.cameFrom) {
path.push(temp.cameFrom);
temp = temp.cameFrom;
}
console.log("Done!");
for (let i = path.length - 1; i >= 0; i--) {
this.ctxGrid.fillStyle = "#ffff00";
this.ctxGrid.fillRect(path[i].x, path[i].y, 14, 14);
await new Promise(resolve =>
setTimeout(() => {
resolve();
}, this.animDelay / 2)
);
}
break;
}
this.removeFromArray(openSet, current);
closedSet.push(current);
let my_neighbors = current.neighbors;
for (let i = 0; i < my_neighbors.length; i++) {
var neighbor = my_neighbors[i];
if (!closedSet.includes(neighbor) && neighbor.type != "Wall") {
let tempG = current.G + 1;
let newPath = false;
if (openSet.includes(neighbor)) {
if (tempG < neighbor.G) {
neighbor.G = tempG;
newPath = true;
}
} else {
neighbor.G = tempG;
newPath = true;
openSet.push(neighbor);
}
if (newPath) {
neighbor.H = this.heuristic(neighbor, end);
neighbor.G = neighbor.F + neighbor.H;
neighbor.cameFrom = current;
}
}
}
//draw
for (let i = 0; i < closedSet.length; i++) { //BLUE
this.ctxGrid.fillStyle = "#4287f5";
this.ctxGrid.fillRect(closedSet[i].x, closedSet[i].y, 14, 14);
}
for (let i = 0; i < openSet.length; i++) { //GREEN
this.ctxGrid.fillStyle = "#00ff00";
this.ctxGrid.fillRect(openSet[i].x, openSet[i].y, 14, 14);
}
await new Promise(resolve =>
setTimeout(() => {
resolve();
}, 10)
);
}
if (openSet.length <= 0) {
//no solution
}
}
Here is my heuristic function:
heuristic(a, b) {
//let d = Math.sqrt(Math.pow(b.I - a.I, 2) + Math.pow(b.J - a.J, 2));
let d = Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
return d;
}

How to fix similar predictions in tenserflow.js

I'm doing a coding challenge from the coding train, and I'm trying to improve on his code. The idea is that the cars are driving around a race track. When I went back to check something, I noticed that I misspelled "activation: sigmoid", as in activation function. When I fixed it, the cars seemed to be driving in circles.
I'm a very new coder (as I am 12 years old), so many things in my code are broken, hard to understand, or just not finished. I'm also pretty new to stack overflow, so I might be breaking a lot of rules.
The link to download my project is here: https://1drv.ms/u/s!ApmY_SAko19ChzCKe5uNT7I9EZAX?e=YUg2ff
The misspelled words are at lines 29 and 34 in the nn.js file.
car.js
function pldistance(p1, p2, x, y) {
const num = abs((p2.y - p1.y) * x - (p2.x - p1.x) * y + p2.x * p1.y - p2.y * p1.x);
const den = p5.Vector.dist(p1, p2);
return num / den;
}
class Car {
constructor(brain, color = [random(255), random(255), random(255)]) {
this.colorGene = color;
this.dead = false;
this.finished = false;
this.fitness = 0;
this.rays = [];
this.wallRays = [];
this.degreeOfSight = degreeOfSight;
this.degreeOfRays = degreeOfSight / (numOfRays - 1);
if (this.degreeOfSight == 360) {
this.degreeOfRays = degreeOfSight / numOfRays;
}
this.pos = createVector(start.x, start.y);
this.vel = createVector();
this.acc = createVector();
this.sight = sight;
this.maxspeed = maxspeed;
this.maxforce = maxTurningSpeed;
this.currentGoal = 0;
this.timeTillDeadC = timeTillDead;
this.timeTillDead = this.timeTillDeadC;
this.goal;
this.rate = mutationRate;
if (degreeOfSight != 360) {
for (let a = -(this.degreeOfSight / 2); a <= this.degreeOfSight / 2; a += this.degreeOfRays) {
this.rays.push(new Ray(this.pos, radians(a)));
}
} else {
for (let a = -(this.degreeOfSight / 2); a < this.degreeOfSight / 2; a += this.degreeOfRays) {
this.rays.push(new Ray(this.pos, radians(a)));
}
}
for (let a = 0; a < 360; a += 45) {
this.wallRays.push(new Ray(this.pos, radians(a)));
}
if (brain) {
this.brain = brain.copy();
} else {
this.brain = new NeuralNetwork(this.rays.length + 2, 16, 2);
}
}
applyForce(force) {
this.acc.add(force);
}
update(x, y) {
this.timeTillDead--;
if (this.timeTillDead <= 0) {
this.dead = true;
}
if (!this.dead || this.finished) {
this.pos.add(this.vel);
this.vel.add(this.acc);
this.vel.limit(this.maxspeed);
this.acc.set(0, 0);
}
for (let i = 0; i < this.rays.length; i++) {
this.rays[i].rotate(this.vel.heading());
}
for (let i = 0; i < this.wallRays.length; i++) {
this.wallRays[i].rotate(this.vel.heading());
}
}
show(walls) {
push();
translate(this.pos.x, this.pos.y);
if (visualization) {
fill(this.colorGene[0], this.colorGene[1], this.colorGene[1]);
} else {
fill(0);
}
stroke(255);
const heading = this.vel.heading();
rotate(heading);
rectMode(CENTER);
rect(0, 0, 10, 5);
pop();
if (!this.dead) {
checkpoints[this.currentGoal].show();
}
for (let i = 0; i < this.rays.length; i++) {
let closest = null;
let record = this.sight;
for (let wall of walls) {
const pt = this.rays[i].cast(wall);
if (pt) {
const d = p5.Vector.dist(this.pos, pt);
if (d < record && d < this.sight) {
record = d;
closest = pt;
}
}
}
if (closest) {
if (showLines) {
ellipse(closest.x, closest.y, 4)
stroke(255, 100)
line(this.pos.x, this.pos.y, closest.x, closest.y);
}
}
}
}
check(checkpoints, walls) {
if (!this.dead) {
this.goal = checkpoints[this.currentGoal];
const d = pldistance(this.goal.a, this.goal.b, this.pos.x, this.pos.y);
if (d < 5) {
this.fitness++;
this.currentGoal++;
this.timeTillDead = this.timeTillDeadC;
if (this.currentGoal == checkpoints.length) {
this.finished = true;
this.fitness = this.fitness * 1.5;
if (endBarrier) {
this.dead = true;
} else {
this.currentGoal = 0;
}
}
}
}
for (let i = 0; i < this.wallRays.length; i++) {
let closest = null;
let record = this.sight;
for (let wall of walls) {
const pt = this.wallRays[i].cast(wall);
if (pt) {
const d = p5.Vector.dist(this.pos, pt);
if (d < record) {
record = d;
closest = pt;
}
}
}
if (record < 4) {
this.dead = true;
}
}
}
look(walls) {
const inputs = [];
for (let i = 0; i < this.wallRays.length; i++) {
let closest = null;
let record = this.sight;
for (let wall of walls) {
const pt = this.rays[i].cast(wall);
if (pt) {
const d = p5.Vector.dist(this.pos, pt);
if (d < record && d < this.sight) {
record = d;
closest = pt;
}
}
}
inputs[i] = map(record, 0, 50, 1, 0);
}
inputs.push(end.x);
inputs.push(end.y);
const output = this.brain.predict(inputs);
let angle = map(output[0], 0, 1, -PI, PI);
let speed = map(output[1], 0, 1, -this.maxspeed, this.maxspeed);
angle += this.vel.heading();
const steering = p5.Vector.fromAngle(angle);
steering.setMag(speed);
steering.limit(this.maxforce);
this.applyForce(steering);
}
mutateDemBabies() {
if (this.finished) {
this.rate = finishingMutationRate;
}
this.brain.mutate(this.rate);
let changeColor = this.brain.mutated();
if (changeColor) {
for (let color of this.colorGene) {
let r = map(random(20), 0, 20, -25, 25);
color += r;
}
}
this.rate = mutationRate;
}
dispose() {
this.brain.dispose();
}
}
nn.js
//<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#1.1.0/dist/tf.min.js"></script>
class NeuralNetwork {
//this how many inputs, hidden, and output nodes there are. modelC is the brain that we want to copy to give to the new bird
constructor(inputNumber, hiddenNumber, outputNumber, modelC) {
if (modelC instanceof tf.Sequential) {
//this is the making a copy of the neural network
this.input_nodes = inputNumber;
this.hidden_nodes = hiddenNumber;
this.output_nodes = outputNumber;
this.model = modelC;
} else {
//this is the creating a random brain
this.input_nodes = inputNumber;
this.hidden_nodes = hiddenNumber;
this.output_nodes = outputNumber;
this.model = this.createBrain();
}
this.changeColor = false;
}
createBrain() {
//the model is the neural network
const model = tf.sequential();
//configuring the hidden layer
const hiddenLayer = tf.layers.dense({
units: this.hidden_nodes,
inputShape: [this.input_nodes],
activaation: "sigmoid"
});
//configuring the output layer
const outputLayer = tf.layers.dense({
units: this.output_nodes,
activaation: "sigmoid"
});
//adding the hidden layer to the model
model.add(hiddenLayer);
//adding the output layer to the model
model.add(outputLayer);
//returning the model
return model;
}
predict(inputs) {
//clearing the tensors after using them
//then returning the output
return tf.tidy(() => {
//creating a tensor with the inputs
const xs = tf.tensor2d([inputs]);
//running the inputs through the neural network
const ys = this.model.predict(xs);
//getting the raw numbers from the tensor object
const outputs = ys.dataSync();
//returning the outputs
return outputs;
});
}
copy() {
//clearing the tensors after using them
//then returning the output
return tf.tidy(() => {
//creating a new neural network
const modelCopy = this.createBrain();
//getting the weights from the old neural network
const weights = this.model.getWeights();
//setting the new weights
modelCopy.setWeights(weights);
//making a new network but this time with all the weights then returning it
return new NeuralNetwork(
this.input_nodes,
this.hidden_nodes,
this.output_nodes,
modelCopy
);
});
}
mutate(rate, colorGene) {
//clearing the tensors after using them
tf.tidy(() => {
this.changeColor = false;
//getting the weights so that we can change them later
const weights = this.model.getWeights();
//the variable that will be holding the mutated weights
const mutatedWeights = [];
for (let i = 0; i < weights.length; i++) {
//getting the shape of the current weights
let shape = weights[i].shape;
//making a copy of the raw numbers from the object tensor
//dataSync gets the numbers, but doesn't make a copy, so slice will make the copy
let values = weights[i].dataSync().slice();
for (let j = 0; j < values.length; j++) {
//if the random number is less than mutation rate the it runs the code
if (random(1) < rate) {
this.changeColor = true;
//mutating the value
//randomGaussianis returns a float from a series of numbers with a mean of 0
values[j] = values[j] + randomGaussian();
}
}
//holding the new value of each weight
mutatedWeights[i] = tf.tensor(values, shape);
}
//setting the mutated weights as the new weights
this.model.setWeights(mutatedWeights);
});
}
mutated() {
if (this.changeColor) {
this.changeColor = false;
return true;
} else {
this.changeColor = false;
return false;
}
}
dispose() {
//disposing the brain so that memory doesn't leak
this.model.dispose();
}
}

How to change voice pitch without noise using web audio javascript?

How do I change voice pitch without noise using web audio in JavaScript?
I tried the code below.
I got my voice with noisy and bit echo mixed.
I want a voice module which is like noiseless.
var pitchShifter = (function () {
var context, audioContext, pitchShifterProcessor, spectrumAudioAnalyser,
sonogramAudioAnalyser;
var validGranSizes = [256, 512, 1024, 2048, 4096, 8192],
grainSize = validGranSizes[1],
pitchRatio = 2.0,
overlapRatio = 0.50;
var filter, compressor;
hannWindow = function (length) {
var window = new Float32Array(length);
for (var i = 0; i < length; i++) {
window[i] = 0.5 * (1 - Math.cos(2 * Math.PI * i / (length - 1)));
}
return window;
};
linearInterpolation = function (a, b, t) {
return a + (b - a) * t;
};
initProcessor = function () {
if (navigator.getUserMedia) {
navigator.getUserMedia({
audio: true
},
function (stream) {
var convolver = audioContext.createConvolver();
compressor = audioContext.createDynamicsCompressor();
compressor.threshold.value = -50;
compressor.knee.value = 40;
compressor.ratio.value = 12;
compressor.reduction.value = -20;
compressor.attack.value = 0;
compressor.release.value = 0.25;
filter = audioContext.createBiquadFilter();
filter.Q.value = 8.30;
filter.frequency.value = 355;
filter.gain.value = 3.0;
filter.type = 'bandpass';
filter.connect(compressor);
compressor.connect(audioContext.destination);
filter.connect(audioContext.destination);
var microphone_stream = audioContext.createMediaStreamSource(
stream);
microphone_stream.connect(filter);
var source = audioContext.createBufferSource();
microphone_stream.connect(pitchShifterProcessor);
},
function (e) {
alert('Error capturing audio.');
}
);
}
if (pitchShifterProcessor) {
pitchShifterProcessor.disconnect();
}
if (audioContext.createScriptProcessor) {
pitchShifterProcessor = audioContext.createScriptProcessor(
grainSize, 1, 1);
} else if (audioContext.createJavaScriptNode) {
pitchShifterProcessor = audioContext.createJavaScriptNode(grainSize,
1, 1);
}
pitchShifterProcessor.buffer = new Float32Array(grainSize * 2);
pitchShifterProcessor.grainWindow = hannWindow(grainSize);
pitchShifterProcessor.onaudioprocess = function (event) {
var inputData = event.inputBuffer.getChannelData(0);
var outputData = event.outputBuffer.getChannelData(0);
for (i = 0; i < inputData.length; i++) {
// Apply the window to the input buffer
inputData[i] *= this.grainWindow[i];
// Shift half of the buffer
this.buffer[i] = this.buffer[i + grainSize];
// Empty the buffer tail
this.buffer[i + grainSize] = 0.0;
}
// Calculate the pitch shifted grain re-sampling and looping the input
var grainData = new Float32Array(grainSize * 2);
for (var i = 0, j = 0.0; i < grainSize; i++, j += pitchRatio) {
var index = Math.floor(j) % grainSize;
var a = inputData[index];
var b = inputData[(index + 1) % grainSize];
grainData[i] += linearInterpolation(a, b, j % 1.0) * this.grainWindow[
i];
}
// Copy the grain multiple times overlapping it
for (i = 0; i < grainSize; i += Math.round(grainSize * (1 -
overlapRatio))) {
for (j = 0; j <= grainSize; j++) {
this.buffer[i + j] += grainData[j];
}
}
// Output the first half of the buffer
for (i = 0; i < grainSize; i++) {
outputData[i] = this.buffer[i];
}
};
pitchShifterProcessor.connect(audioContext.destination);
};
return {
init: function () {
if ('AudioContext' in window) {
audioContext = new AudioContext();
} else {
alert('Your browser does not support the Web Audio API');
return;
}
initProcessor();
}
}
}());
window.requestAnimFrame = (function () {
return (window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
});
})();
window.addEventListener("DOMContentLoaded", pitchShifter.init, true);
You can use the PitchShifter in SoundTouchJS for this. I currently use this in my CDGPlayer for changing the 'key' for a user.

Extract images from a single PDF page using PDFJS

Is there a way to extract images from a single PDF page using PDFJS framework?
After some googling, I found this discussion talking about that, but unfortunately its not very specific, he talks about passing an imageLayer to the CanvasGraphics object, but I didn't recognize what he does mean by that.
let imgIndex = 1;
let opList = await page.getOperatorList();
for (let k = 0; k < opList.fnArray.length; k++) {
if (opList.fnArray[k] == pdfjsLib.OPS.paintJpegXObject || opList.fnArray[k] == pdfjsLib.OPS.paintImageXObject) {
function getImage() {
return new Promise(async function (res, rej) {
let img = null
try {
//-------either get data from page.objs.get
img = page.objs.get(opList.argsArray[k][0])
} catch (err) {
if (opList.argsArray[k][0].startsWith("g_")) {
//---------or get data from page.commonObjs.get
img = page.commonObjs.get(opList.argsArray[k][0])
} else {
res()
}
}
try {
//------------------ directly creating image data from returned array does not print proper image also sometimes throw error.
// var idata = new ImageData(img.data, img.width);
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext('2d');
//------------------- below function will process data and print proper image on provided canvas context. kind parameter in returned data is used in this function to prcess the data
putBinaryImageData(ctx, img)
// ctx.putImageData(idata, 0, 0);
function getCanvasBlob(canvas) {
return new Promise(function (resolve, reject) {
canvas.toBlob(function (blob) {
resolve(blob)
})
})
}
getCanvasBlob(canvas).then((blob) => {
zip.folder('images').file(`page-${i}-image-${imgIndex}`, blob, { base64: false });
imgIndex++;
res()
}).catch((err) => {
// console.log(err)
res()
})
} catch (err) {
console.log(err)
res()
}
})
}
await getImage()
}
}
IMP ----------- Below function is taken from source code of PDF.js to convert image data to proper images as the data returned from pdf.js inbuilt function for images is uint8clampedarray which can not be used as it is for images, this data needs to be processed which is being done using below function.
export function putBinaryImageData(ctx, imgData, transferMaps = null) {
const FULL_CHUNK_HEIGHT = 16;
const ImageKind = {
GRAYSCALE_1BPP: 1,
RGB_24BPP: 2,
RGBA_32BPP: 3
};
if (typeof ImageData !== "undefined" && imgData instanceof ImageData) {
ctx.putImageData(imgData, 0, 0);
return;
}
const height = imgData.height,
width = imgData.width;
const partialChunkHeight = height % FULL_CHUNK_HEIGHT;
const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
let srcPos = 0,
destPos;
const src = imgData.data;
const dest = chunkImgData.data;
let i, j, thisChunkHeight, elemsInThisChunk;
let transferMapRed, transferMapGreen, transferMapBlue, transferMapGray;
if (transferMaps) {
switch (transferMaps.length) {
case 1:
transferMapRed = transferMaps[0];
transferMapGreen = transferMaps[0];
transferMapBlue = transferMaps[0];
transferMapGray = transferMaps[0];
break;
case 4:
transferMapRed = transferMaps[0];
transferMapGreen = transferMaps[1];
transferMapBlue = transferMaps[2];
transferMapGray = transferMaps[3];
break;
}
}
if (imgData.kind === ImageKind.GRAYSCALE_1BPP) {
const srcLength = src.byteLength;
const dest32 = new Uint32Array(dest.buffer, 0, dest.byteLength >> 2);
const dest32DataLength = dest32.length;
const fullSrcDiff = width + 7 >> 3;
let white = 0xffffffff;
let black = _util.IsLittleEndianCached.value ? 0xff000000 : 0x000000ff;
if (transferMapGray) {
if (transferMapGray[0] === 0xff && transferMapGray[0xff] === 0) {
[white, black] = [black, white];
}
}
for (i = 0; i < totalChunks; i++) {
thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
destPos = 0;
for (j = 0; j < thisChunkHeight; j++) {
const srcDiff = srcLength - srcPos;
let k = 0;
const kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7;
const kEndUnrolled = kEnd & ~7;
let mask = 0;
let srcByte = 0;
for (; k < kEndUnrolled; k += 8) {
srcByte = src[srcPos++];
dest32[destPos++] = srcByte & 128 ? white : black;
dest32[destPos++] = srcByte & 64 ? white : black;
dest32[destPos++] = srcByte & 32 ? white : black;
dest32[destPos++] = srcByte & 16 ? white : black;
dest32[destPos++] = srcByte & 8 ? white : black;
dest32[destPos++] = srcByte & 4 ? white : black;
dest32[destPos++] = srcByte & 2 ? white : black;
dest32[destPos++] = srcByte & 1 ? white : black;
}
for (; k < kEnd; k++) {
if (mask === 0) {
srcByte = src[srcPos++];
mask = 128;
}
dest32[destPos++] = srcByte & mask ? white : black;
mask >>= 1;
}
}
while (destPos < dest32DataLength) {
dest32[destPos++] = 0;
}
ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
}
} else if (imgData.kind === ImageKind.RGBA_32BPP) {
const hasTransferMaps = !!(transferMapRed || transferMapGreen || transferMapBlue);
j = 0;
elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4;
for (i = 0; i < fullChunks; i++) {
dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
srcPos += elemsInThisChunk;
if (hasTransferMaps) {
for (let k = 0; k < elemsInThisChunk; k += 4) {
if (transferMapRed) {
dest[k + 0] = transferMapRed[dest[k + 0]];
}
if (transferMapGreen) {
dest[k + 1] = transferMapGreen[dest[k + 1]];
}
if (transferMapBlue) {
dest[k + 2] = transferMapBlue[dest[k + 2]];
}
}
}
ctx.putImageData(chunkImgData, 0, j);
j += FULL_CHUNK_HEIGHT;
}
if (i < totalChunks) {
elemsInThisChunk = width * partialChunkHeight * 4;
dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
if (hasTransferMaps) {
for (let k = 0; k < elemsInThisChunk; k += 4) {
if (transferMapRed) {
dest[k + 0] = transferMapRed[dest[k + 0]];
}
if (transferMapGreen) {
dest[k + 1] = transferMapGreen[dest[k + 1]];
}
if (transferMapBlue) {
dest[k + 2] = transferMapBlue[dest[k + 2]];
}
}
}
ctx.putImageData(chunkImgData, 0, j);
}
} else if (imgData.kind === ImageKind.RGB_24BPP) {
const hasTransferMaps = !!(transferMapRed || transferMapGreen || transferMapBlue);
thisChunkHeight = FULL_CHUNK_HEIGHT;
elemsInThisChunk = width * thisChunkHeight;
for (i = 0; i < totalChunks; i++) {
if (i >= fullChunks) {
thisChunkHeight = partialChunkHeight;
elemsInThisChunk = width * thisChunkHeight;
}
destPos = 0;
for (j = elemsInThisChunk; j--;) {
dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++];
dest[destPos++] = 255;
}
if (hasTransferMaps) {
for (let k = 0; k < destPos; k += 4) {
if (transferMapRed) {
dest[k + 0] = transferMapRed[dest[k + 0]];
}
if (transferMapGreen) {
dest[k + 1] = transferMapGreen[dest[k + 1]];
}
if (transferMapBlue) {
dest[k + 2] = transferMapBlue[dest[k + 2]];
}
}
}
ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
}
} else {
throw new Error(`bad image kind: ${imgData.kind}`);
}
}

'Arc is not a constructor' error

I am getting an error saying Arc is not a constructor. I have checked my code and can't understand why.
/*
Exception: Arc is not a constructor
RouteFinder/this.getPairs#Scratchpad/8:72:6
#Scratchpad/8:5:3
*/
The other answers for this error suggest that this because Arc has previously been defined, but I cant find anywhere that it is. This is a big chunk of code, so scroll down for the error - it is commented where it is
var lats = [ 51.445371, 51.45526, 51.426765, 51.441304 ]
var lons = [ -0.077581, -0.113248, -0.13091, -0.060596 ]
var finder = new RouteFinder(lats, lons);
finder.getPairs();
var nodeList = ''
for(var count = 1; count < lats.length; count++) {
nodeList += count;
}
finder.permutation("", nodeList);
finder.removeDuplicateRoutes();
var shortestRoute = finder.getShortestRoute();
var finalRouteOrder = [];
shortestRoute.nodeList.forEach(function(node) {
finalRouteOrder.push(+node);
});
alert(finalRouteOrder);
var Route = function() {
this.totalWeight = 0;
this.nodeList = [];
};
var Node = function() {
this.lat = 0;
this.lon = 0;
this.number = 0;
};
var Arc = function() {
this.startNode = new Node();
this.endNode = new Node();
this.weight = 0;
};
function reverseString(initialString) {
var reversed = '';
for(var count = initialString.length -1; count > -1; count--) {
reversed += initialString.charAt(count);
}
return reversed;
}
function calcDistance(lat1, lng1, lat2, lng2) {
var earthRadius = 6371;
var dLat = (lat2 - lat1)/180*Math.PI;
var dLng = (lng2 - lng1)/180*Math.PI;
var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1/180*Math.PI) * Math.cos(lat2/180*Math.PI) * Math.sin(dLng/2) * Math.sin(dLng/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var dist = earthRadius * c;
return dist;
}
function RouteFinder(lats, lons) {
this.latArray = lats;
this.lonArray = lons;
this.orders = [];
this.arcArray = [];
this.routes = [];
this.shortestRoute;
this.numOfPoints = lats.length - 1;
this.shortestRouteLength = -1;
this.getPairs = function() {
var timesLooped = 0;
for(var count1 = 0; count1 < this.numOfPoints; count1++) {
for(var count2 = 0; count2 < (this.numOfPoints - count1); count2++) {
//I get an error here for new Arc()
this.arcArray.push(new Arc());
this.arcArray[timesLooped].startNode = {
number: count1,
};
this.arcArray[timesLooped].endNode = {
number: this.numOfPoints - count2,
};
this.arcArray[timesLooped].weight = calcDistance(this.latArray[count1], this.lonArray[count1], this.latArray[this.numOfPoints - count2], this.lonArray[this.numOfPoints - count2]);
timesLooped++;
}
}
};
this.permutation = function(prefix, str) {
var n = str.length;
if(n === 0) this.orders.push('0' + prefix + '0');
else {
for(var i = 0; i <n; i++) {
this.permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i + 1, n));
}
}
};
this.removeDuplicateRoutes = function() {
var numberOfPermutations = this.orders.length -1;
var temp;
var size;
var toRemove = [];
for(var count1 = 0; count1 < numberOfPermutations; count1++) {
for(var count2 = 0; count2 < (numberOfPermutations - count1); count2++) {
if(this.orders[count1] == reverseString(this.orders[numberOfPermutations - count2])) {
toRemove.push(count1);
}
}
}
size = toRemove.length;
for(var count3 = 0; count3 < size; count3++) {
temp = toRemove[size - 1- count3];
var index = this.orders.indexOf(temp);
if(index > -1) {
temp.splice(index, 1);
}
}
};
this.getShortestRoute = function() {
var routesMade = 0;
for(var routeNumber = 0; routeNumber < (this.orders.length -1); routeNumber++) {
this.routes.push(new Route());
this.routes[routesMade].totalWeight = 0;
for(var count1 = 0; count1 < this.orders[routeNumber].length; count1++) {
this.routes[routesMade].nodeList.push(+this.orders[routeNumber].charAt(count1));
}
for(var count2 = 1; count2 < this.orders[routeNumber].length; count2++) {
for(var count3 = 0; count3 < this.arcArray.length; count3++) {
if(this.routes[routesMade].nodeList[count2 - 1] === this.arcArray[count3].startNode.number) {
if(this.routes[routesMade].nodeList[count2] === this.arcArray[count3].endNode.number) {
this.routes[routesMade].totalWeight += this.arcArray[count3].weight;
}
} else if (this.routes[routesMade].nodeList[count2 - 1] === this.arcArray[count3].endNode.number) {
if(this.routes[routesMade].nodeList[count2] === this.arcArray[count3].startNode.number) {
this.routes[routesMade].totalWeight += this.arcArray[count3].weight;
}
}
}
}
if(!this.shortestRoute) {
this.shortestRoute = this.routes[routesMade];
} else if(this.routes[routesMade].totalWeight < this.shortestRoute.totalWeight) {
this.shortestRoute = this.routes[routesMade];
}
routesMade++;
}
return this.shortestRoute;
};
}
I'm tearing my hair out trying to work out the problem. Help is greatly appreciated, thanks!
This
var finder = new RouteFinder(lats, lons);
gets executed before Arc variable gets its value (function). Thus at the moment of RouteFinder call that Arc variable is undefined and cannot be used as a constructor.
Update: it is about finder.getPairs(); actually where you try to call that new Arc();
You need to have Route, Node, and Arc like this:
function Route() {
this.totalWeight = 0;
this.nodeList = [];
}
function Node() {
this.lat = 0;
this.lon = 0;
this.number = 0;
}
function Arc() {
this.startNode = new Node();
this.endNode = new Node();
this.weight = 0;
}
The issue is that Arc is not yet defined. Either move your function expression assignment (var Arc = function ...) to the top of your script or convert them to function definition statements like this
function Arc() {
this.startNode = new Node();
this.endNode = new Node();
this.weight = 0;
}
Statements are hoisted and their order does not matter, but assignment to var happens in the order they appear in the file (the declaration is hoisted, but the assignment isn't).
Same goes for your Route and Node functions.
Read more about var hoisting on MDN.

Categories

Resources