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.
Related
I am making a tree with space-colonization algorithm in javascript. (with p5.js)
I followed the tutorial of https://www.youtube.com/watch?v=kKT0v3qhIQY&ab_channel=TheCodingTrain
or in C#
http://www.jgallant.com/procedurally-generating-trees-with-space-colonization-algorithm-in-xna/
I want to make a customized area (in this case a circle) where the leaves are generated randomly.
in Leaf.js I try to include some calculations of how the leaves get the random Coordinates within the circle.
So there is sketch.js , leaf.js, branch.js, tree.js
//leaf.js
function Leaf() {
function getChord(){
var r = 150;
var angle = random(0, 2 * PI);
var xChord = 2*r + sqrt(r) * cos(angle);
var yChord = r + sqrt(r) * sin(angle);
return (createVector(xChord, yChord));
}
this.pos = getChord();
this.reached = false;
// // var t = 2 * PI * random(0,1);
// // var r = sqrt(random(0,1));
// // var x = r * cos(t);
// // var y = r * sin(t);
// // this.pos = createVector(x, y);
// this.reached = false;
this.show = function() {
fill(58, 126, 34);
noStroke();
ellipse(this.pos.x, this.pos.y, 4, 4);
};
}
//branch.js
function Branch(parent, pos, dir) {
this.pos = pos;
this.parent = parent;
this.dir = dir;
this.origDir = this.dir.copy();
this.count = 0;
this.len = 3;
this.reset = function() {
this.dir = this.origDir.copy();
this.count = 0;
};
this.next = function() {
var nextDir = p5.Vector.mult(this.dir, this.len);
var nextPos = p5.Vector.add(this.pos, nextDir);
var nextBranch = new Branch(this, nextPos, this.dir.copy());
return nextBranch;
};
this.show = function() {
if (parent != null) {
stroke(151, 53, 48);
strokeWeight(1);
line(this.pos.x, this.pos.y, this.parent.pos.x, this.parent.pos.y);
}
};
}
And then in tree.js I push every leaf into leaves.
//tree.js
function Tree() {
this.leaves = [];
this.branches = [];
for (var i = 0; i < 1500; i++) {
this.leaves.push(new Leaf());
}
var pos = createVector(width / 2, height);
var dir = createVector(0, -1);
var root = new Branch(null, pos, dir);
this.branches.push(root);
var current = root;
var found = false;
while (!found) {
for (var i = 0; i < this.leaves.length; i++) {
var d = p5.Vector.dist(current.pos, this.leaves[i].pos);
if (d < max_dist) {
found = true;
}
}
if (!found) {
var branch = current.next();
current = branch;
this.branches.push(current);
}
}
this.grow = function() {
for (var i = 0; i < this.leaves.length; i++) {
var leaf = this.leaves[i];
var closestBranch = null;
var record = max_dist;
for (var j = 0; j < this.branches.length; j++) {
var branch = this.branches[j];
var d = p5.Vector.dist(leaf.pos, branch.pos);
if (d < min_dist) {
leaf.reached = true;
closestBranch = null;
break;
} else if (d < record) {
closestBranch = branch;
record = d;
}
}
if (closestBranch != null) {
var newDir = p5.Vector.sub(leaf.pos, closestBranch.pos);
newDir.normalize();
closestBranch.dir.add(newDir);
closestBranch.count++;
}
}
for (var i = this.leaves.length - 1; i >= 0; i--) {
if (this.leaves[i].reached) {
this.leaves.splice(i, 1);
}
}
for (var i = this.branches.length - 1; i >= 0; i--) {
var branch = this.branches[i];
if (branch.count > 0) {
branch.dir.div(branch.count + 1);
this.branches.push(branch.next());
branch.reset();
}
}
};
this.show = function() {
for (var i = 0; i < this.leaves.length; i++) {
this.leaves[i].show();
}
for (var i = 0; i < this.branches.length; i++) {
this.branches[i].show();
}
};
}
//sketch.js
var tree;
var max_dist = 30;
var min_dist = 10;
function setup() {
createCanvas(600, 600);
tree = new Tree();
}
function draw() {
background(111, 149, 231);
tree.show();
tree.grow();
}
Some how in the function getChord I think there is an infinite loop or having trouble getting the random value? Because it is not loading at all... It works when I change this.pos = getChord(); to this.pos = createVector(random(width),random(height-100);
Does anyone know how to solve this?
Or how to write codes to make an area of the circle where the leaves can be generated?
Thank you!
I want to make a dynamic water pipe with water flowing. The front picture is an error message.
The following picture is a method in the method in the vue page. I don't know if it will report an error. If you don't call this method, nothing will be reported.
The following code is the js file that introduces the vue page
//构造函数
function Createline(config) {
this.c = 0;
this.lines = [];
var self = this;
//初始化线
(function (self){
if(config.fx == "w"){
var number = config.canvas_w / (config.width + config.width/2 + config.jiange*2);
number = Math.ceil(number) + 1;
for(var n = 0 ; n < number ; n++){
var mxx = config.canvas_w - n*(config.width+config.width/2+config.jiange*2);
var lines_data = {
mx:mxx,
lx:mxx - config.width,
my:config.my,
ly:config.ly,
vx:config.vx,
vy:config.vy,
}
self.lines.push(lines_data);
var lines_data2 = {
mx:mxx-config.width-config.jiange,
lx:mxx-config.width-config.jiange-config.width/2,
my:config.my,
ly:config.ly,
vx:config.vx,
vy:config.vy,
}
self.lines.push(lines_data2);
}
}
if(config.fx == "h"){
var number = config.canvas_w / (config.width + config.width/2 + config.jiange*2);
number = Math.ceil(number) + 1;
for(var n = 0 ; n < number ; n++){
var myy = config.canvas_h - n*(config.width+config.width/2+config.jiange*2);
var lines_data3 = {
mx:config.mx,
lx:config.lx,
my:myy,
ly:myy - config.width,
vx:config.vx,
vy:config.vy,
}
self.lines.push(lines_data3);
var lines_data4 = {
mx:config.mx,
lx:config.lx,
my:myy-config.width-config.jiange,
ly:myy-config.width-config.jiange-config.width/2,
vx:config.vx,
vy:config.vy,
}
self.lines.push(lines_data4);
}
}
})(self);
}
//开始
Createline.prototype.begin = function (element,config) {
var canvasObj = document.getElementById(element);
var self = this;
var canvas = {
line_w: config.line_w || 3, //线条厚度
vx: config.vx || 0,//x轴运动速度
vy:config.vy || 0,//Y轴速度
color:config.color || "blue",//线条颜色
canvas_w:config.canvas_w || 0,//画布宽度
canvas_h:config.canvas_h || 0,//画布高度
mx: config.mx || 0,//线的开始位置X坐标
my: config.my || 0,//线的开始位置Y坐标
lx: config.lx || 0,//线的结束位置X坐标
ly: config.ly || 0,//线的结束位置Y坐标
fx:config.fx || "w",//运动方向 w 水平 ,h: 垂直
width:config.width || 20,//线的长度
jiange:config.jiange || 10, //线的间隔
}
if(canvasObj.getContext("2d")){
canvas.ctx = canvasObj.getContext("2d"),
canvasObj.width = canvas.canvas_w;
canvasObj.height = canvas.canvas_h;
}else{
console.log("当前环境不支持canvas");
return null;
}
setInterval(function(){
self.createline(self,canvas);
if(canvas.fx == "w"){
self.updateline_w(self,canvas);
}
if(canvas.fx == "h"){
self.updateline_h(self,canvas);
}
self.addline(self,canvas);
},config.time);
return canvas.ctx;
}
//画线
Createline.prototype.createline = function(self,canvas){
var content = canvas.ctx;
content.clearRect(0,0,canvas.canvas_w,canvas.canvas_h);
for(var i = 0 ; i < self.lines.length ; i++){
content.beginPath();
content.moveTo(self.lines[i].mx,self.lines[i].my);
//线经过的转折点或结束点
content.lineTo(self.lines[i].lx,self.lines[i].ly);
//线条宽度
content.lineWidth = canvas.line_w;
content.strokeStyle = canvas.color;
content.stroke();
//线条颜色
content.closePath();
//画线
}
}
//改变数据 水平运动
Createline.prototype.updateline_w = function(self,canvas){
for (var i = 0 ; i < self.lines.length ; i++) {
self.lines[i].mx = self.lines[i].mx + self.lines[i].vx;
self.lines[i].lx = self.lines[i].lx + self.lines[i].vx;
}
//超出画布的线条从数组内删除,减少系统消耗
var cnt = [];
for (var j = 0 ;j < self.lines.length ; j++) {
if(self.lines[j].lx > canvas.canvas_w){
cnt.push(j);
}
}
for(var k = 0; k < cnt.length ; k++){
self.lines.splice(k,1);
}
}
//改变数据 垂直运动
Createline.prototype.updateline_h = function(self,canvas){
for (var i = 0 ; i < self.lines.length ; i++) {
self.lines[i].my = self.lines[i].my + lines[i].vy;
self.lines[i].ly = self.lines[i].ly + lines[i].vy;
}
//超出画布的线条从数组内删除,减少系统消耗
var cnt = [];
for (var j = 0 ;j < self.lines.length ; j++) {
if( self.lines[j].ly > canvas.canvas_h){
cnt.push(j);
}
}
for(var k = 0; k < cnt.length ; k++){
self.lines.splice(k,1);
}
}
//增加线
Createline.prototype.addline = function(self,canvas){
var length = self.lines.length;
//横线
if(canvas.fx == "w"){
//判断是否需要生成线
if(self.lines[length-1].lx > 0){
//起点位置 等于 左右一根线的坐标减去间隔
var ww = self.lines[length - 1].lx - canvas.jiange;
//判断长短
if(self.c == 0){
var jg = canvas.width;
self.c = 10;
}else{
var jg = canvas.width/2;
self.c = 0;
}
var lxx = ww - jg;
var data = {
mx:ww,
lx:lxx,
my:canvas.my,
ly:canvas.ly,
vx:canvas.vx,
vy:canvas.vy,
}
self.lines.push(data);
}
}
//垂直
if(canvas.fx == "h"){
if(length>0){
//判断是否需要生成线
if(self.lines[length-1].ly > 0){
//起点位置 等于 左右一根线的坐标减去间隔
var my = self.lines[length - 1].ly - canvas.jiange;
//判断长短
if(c == 0){
var jg = canvas.width;
c = 10;
}else{
var jg = canvas.width/2;
c = 0;
}
var ly = my - jg;
var data = {
mx:canvas.mx,
lx:canvas.lx,
my:my,
ly:ly,
vx:canvas.vx,
vy:canvas.vy,
}
self.lines.push(data);
}
}else{
var data = {
mx:canvas.mx,
my:canvas.my,
lx:canvas.lx,
ly:canvas.ly,
vx:canvas.vx,
vy:canvas.vy,
}
self.lines.push(data);
}
}
}
export{
Createline
}
You need to use new when creating a instance for a constructor that uses this:
var cre = new Createline(data);
When a function is executed using new it does the following:
function User(name) {
// this = {}; (implicitly)
// add properties to this
this.name = name;
this.isAdmin = false;
// return this; (implicitly)
}
In the following code, the console.log from the line 92 and 93 (switchPosition function) doesn't provide the same result. I am, I have to admit, stuck.
Any thoughts, ideas, explanations?
Thanks you for the time taken,
var Carrousel = (function () {
var self = {},
config = {
item: 3, // item to be displayed
scroll: 2 // number of items to be scrolled
},
container = null,
items = null,
nbItems = null,
nbSlide = null,
position = [],
searchPositionDepending = []
;
self.init = function (opts) {
options = opts || {}
execute();
}
// Private Method
execute = function () {
container = document.getElementById('carrousel');
items = document.getElementsByClassName('flux');
var containerWidth = container.offsetWidth;
var containerHeight = items[0].offsetHeight * 1.5;
container.style.height = '' + containerHeight + '';
nbItems = document.getElementsByClassName('flux').length;
nbSlide = nbItems / config.item;
// Initialisation du Carrousel
for (i = 0; i < nbItems; i++) {
items[i].style.width = '' + (containerWidth / config.item) + '';
items[i].style.display = 'none';
items[i].style.position = 'absolute';
items[i].style.top = "0";
items[i].style.left = "0";
items[i].setAttribute('data-position', '' + (i + 1) + '');
items[i].setAttribute('data-number', '' + i + '');
}
searchPosition();
placement();
document.getElementById('next').onclick = function () {
next();
searchPosition();
switchPosition();
placement();
// position();
}
document.getElementById('previous').onclick = function () {
// previous();
// searchPosition();
// position();
}
}
searchPosition = function () {
for (i = 0; i < config.item; i++) {
searchPositionDepending[i] = (function () { //Appending a function searchPosition per item displayed
for (j = 1; j <= config.item; j++) { //Passing through the first items to get their position
if (items[i].dataset.position === '' + j + '') {
position[j] = items[i];
return true;
} else {
}
}
;
})();
}
}
switchPosition = function () {
for (i = 0, j = 0; i < nbItems; i++, j++) {
if (items[i].dataset.position === '' + j + '') {
position[i] = position[i];
}
}
for (i = config.item, j = 1; i < nbItems; i++, j++) { //Replacing in good order, except for the one that are place into the variable position[];
items[i] = items[j];
}
for (i = (nbItems - config.item +1), j = 1; i <= nbItems; i++, j++) { //Replacing in good order the one that are place into variable position[];
items[i] = position[j];
console.log(i);
console.log(j);
console.log(position[j]);
console.log(items[i]);
}
for (i = 0; i < nbItems; i++) {
console.log(items[i]);
}
console.log(items[10]);
}
placement = function () {
for (i = 1; i <= config.item; i++) {
var rect = items[0].getBoundingClientRect();
item_width = Math.floor(rect.width);
item_height = Math.floor(rect.height);
var x = item_width * (i - 1) * 1.1;
items[i].style.display = 'block';
items[i].style.transform = "translate3D(" + x + "px, 0px, 0px)";
}
}
next = function () {
for (i = config.item, j = 1; i < nbItems; i++, j++) { //Updating all dataset position, except for the items that are displayed.
items[i].dataset.position = j;
}
for (i = 1, j = 2; i <= config.item; i++, j--) {
position[i].dataset.position = nbItems - j;
position[i].style.display = "none";
}
}
return self;
})();
I am trying to sum the ranged values but for some reason it's not summing. Any idea why?
I am not a very good in JavaScript but I have some knowledge...
function bag(input) {
var sheet = SpreadsheetApp.getActiveSpreadsheet()
var AllValues = sheet.getRange(input).getValues();
var FValue = "";
var TotalGold = 0;
var TotalSilver = 0;
var TotalBronze = 0;
for(i = 0; i < AllValues.length; i++) {
var total = AllValues[i][0].split(" ");
for(i = 0; i < total.length; i++){
if (total[i].indexOf("g") >= 0) {
var value = total[i].replace("g","");
var gold = value * 1;
TotalGold = TotalGold + gold;
}
else if (total[i].indexOf("s") >= 0) {
var value = total[i].replace("s","");
var silver = value * 1;
TotalSilver = TotalSilver + silver;
}
else if (total[i].indexOf("b") >= 0) {
var value = total[i].replace("b","");
var bronze = value * 1;
TotalBronze = TotalBronze + bronze;
}
else {
return null;
}
}
}
return TotalGold + "g " + TotalSilver + "s " + TotalBronze + "b";
}
It appears you are overwriting your value of i in the nested iteration. Pick another identifier. E.g: for (var j = 0; j < total.length; j++) { ... }
Keep in mind this is unfinished, the only question I have is why does the console.log produce this output?
/>B /* This is what I expected */
/>B-D /* The second output I expected to be just ">/D" I am conused as to how it is coming up with >/"B-D" */
graphArray = ["4","A","B","C","D","A-B","B-D","B-C","C-D"];
pointsArray = [];
linesArray = [];
nodes = graphArray[0];
for (i = 1; i < graphArray.length; i++) {
if (i <= nodes) {
pointsArray.push(graphArray[i]);
}
if (i > nodes) {
linesArray.push(graphArray[i]);
}
}
nextpoint = pointsArray[0];
patt = new RegExp(/-.*/);
patt2 = new RegExp(nextpoint + "-");
for (i = 0; i < linesArray.length; i++) {
x = 0;
while (x < linesArray.length) {
if (linesArray[x].replace(patt,"") === nextpoint) {
nextpoint = linesArray[x].replace(patt2,"");
console.log(nextpoint);
}
x++;
}
}
Edit: Smacks forehead it must be getting too late for me I can't believe I missed that. Thank you for point that out. Solved.
Your patt2 = new RegExp(nextpoint + "-"); should be inside the loop
for (i = 0; i < linesArray.length; i++) {
x = 0;
while (x < linesArray.length) {
patt2 = new RegExp(nextpoint + "-");
if (linesArray[x].replace(patt,"") === nextpoint) {
nextpoint = linesArray[x].replace(patt2,"");
console.log(nextpoint);
}
x++;
}
}