I have an error and i cannot get this out of my script. I think it's because of some double entries.. but i expect that it ignores the long and lat then:
// creeert een geordende database van de gebruikte woorden
var wordConnection = new Array();
var wordCoords = new Array();
var index = 0;
var indexY = 0;
var brightRed;
var randomnumber = Math.floor(Math.random() * 256);
var randomnumber2 = Math.floor(Math.random() * 256);
var randomnumber3 = Math.floor(Math.random() * 256);
var colourRandom = colorToHex('rgb('+randomnumber+', '+randomnumber+', '+randomnumber+')');
// document.writeln(randomnumber)
for (var x = 0; x < wordSort.length - 1; x++)
{
var wordSort1 = wordSort[x];
var wordSort2 = wordSort[x + 1];
// if ((latSort[x] != latSort[x+1])&& (longSort[x] != longSort[x+1]) ){
if (latSort[x] != undefined){
document.writeln(latSort[x]);
document.writeln("----");
document.writeln(longSort[x]);
wordCoords[indexY] = new google.maps.LatLng(latSort[x], longSort[x]);
indexY++;
}
// }
if (wordSort1 != wordSort2)
{
colourRandom = colorToHex('rgb('+randomnumber+', '+randomnumber2+', '+randomnumber3+')');
wordConnection[index] = new google.maps.Polygon(
{
paths: wordCoords,
strokeColor: colourRandom,
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35
});
wordConnection[index].setMap(map);
wordCoords.length = 0;
indexY = 0;
randomnumber = Math.floor(Math.random() * 256);
randomnumber2 = Math.floor(Math.random() * 256);
randomnumber3 = Math.floor(Math.random() * 256);
index++;
}
}
It doesn't give any faults :(
i get a list of words combined with a list of geo locations. It inserts them into an array. The words are sorted alphabetically. If the next word doesn't resemble, then it shows the array of geo locations and makes a new one. I've discovered that it works, when i insert an alert to count the 'index' var :S Maybe i put it in the wrong place in the whole script? (Don't think so)
Related
I am trying to make a function that randomizes the placement of some clouds I imported, but the problem is, it generates the amount of clouds, but in the same position! I randomized the position, but when the code runs I have like 10 clouds in the same position. What can I do? this is the code:
loader.load('/clouds/clouds1/scene.gltf', function (clouds1) {
var clouds1array = []
function addClouds1(){
for (var i = 1; i < 10; i++) {
const clouds1Mesh = clouds1.scene
const clouds1Position = clouds1Mesh.position
clouds1Position.x = Math.random() * 10
clouds1Position.y = Math.random() * 10
clouds1Position.z = (Math.random() - 0.5 ) * 300
clouds1Mesh.scale.setX(0.05)
clouds1Mesh.scale.setY(0.05)
clouds1Mesh.scale.setZ(0.05)
scene.add(clouds1Mesh)
clouds1array.push(clouds1Mesh)
}
}
addClouds1()
})
edit: clouds1.scene structure is this:
I don't know why it has this amount of children, I tried to solve with the answer, but it still does not work. The 3rd child in the end contains the mesh, and I tried using that for it to work, but it says that I cannot use it in the scene.add() function
edit: I solved the problem! I just had to put the for loop outside the load function
for(let i = 0; i < 30; i+= 3)
loader.load('/clouds/clouds1/scene.gltf', function (clouds1) {
const cloud = clouds1.scene
const child1 = clouds1.scene.children[0].children[0].children[0].children[2].children[0]
child1.material = new THREE.MeshStandardMaterial({ emissive: 'white', emissiveIntensity: 0.5})
cloud.scale.set(0.05, 0.05, 0.05)
cloud.position.x = (Math.random() - 0.5) * 500
cloud.position.y = (Math.random() + ((Math.random() + 20 ) + 70))
cloud.position.z = (Math.random() - 1) * 500
cloud.rotation.x = Math.random()
cloud.rotation.y = Math.random()
cloud.rotation.z = Math.random()
scene.add(cloud)
})
The GLTFLoader results, which you have as clouds1 is a generic object, from which you properly extract clouds1.scene. However, clouds1.scene is also a single Scene object. If you have 10 clouds in the GLTF model you loaded, then clouds1.scene will have 10 children, and you will need to loop through them like this:
loader.load('/clouds/clouds1/scene.gltf', function (clouds1) {
var clouds1array = []
const clouds1Children = clouds1.scene.children
for (var i = 1; i < 10; i++) {
const clouds1Mesh = clouds1Children[i]
const clouds1Position = clouds1Mesh.position
clouds1Position.x = Math.random() * 10
clouds1Position.y = Math.random() * 10
clouds1Position.z = (Math.random() - 0.5 ) * 300
clouds1Mesh.scale.setX(0.05)
clouds1Mesh.scale.setY(0.05)
clouds1Mesh.scale.setZ(0.05)
scene.add(clouds1Mesh)
clouds1array.push(clouds1Mesh)
}
})
In my project, I want my array to increase in size every 5 seconds. I tried to use setInterval to call a function to do this, but it resets my array every 5 seconds with an increased amount rather than naturally growing. Is there a way to increase the amount without having to reset the array each time?
These are the functions I am using to call my "plants":
var myPlants = new Array();
var plantSpawn = 0;
function createPlants() {
reproducePlants();
setInterval(reproducePlants, 5000);
}
function reproducePlants() {
plantSpawn += 5;
for(var i=0; i<plantSpawn; i++){
var rr = Math.round(Math.random() * 150);
var gg = Math.round(Math.random() * 255);
var bb = Math.round(Math.random() * 150);
var plant = new Object();
plant.x = Math.random() * canvas.width;
plant.y = Math.random() * canvas.height;
plant.rad = 2;
plant.skin = 'rgba('+rr+','+gg+','+bb+', 1)';
myPlants[i] = plant;
}
}
You are explicitly reseting all the values of the array when you do this:
for(var i=0; i < plantSpawn; i++){... myPlants[i] = plant; ...}
Note that plantSpawn will hold the new array size, so you are looping over all the old indexes plus the new ones and re-assigning the values on they.
So, instead you can add 5 new elements to the array with Array.push() this way:
var myPlants = new Array();
var plantsInc = 5;
function createPlants()
{
reproducePlants();
setInterval(reproducePlants, 5000);
}
function reproducePlants()
{
// Push N new plants on the array.
for (var i = 0; i < plantsInc; i++)
{
var rr = Math.round(Math.random() * 150);
var gg = Math.round(Math.random() * 255);
var bb = Math.round(Math.random() * 150);
var plant = new Object();
plant.x = Math.random() * canvas.width;
plant.y = Math.random() * canvas.height;
plant.rad = 2;
plant.skin = 'rgba('+rr+','+gg+','+bb+', 1)';
// Push a new plant on the array.
myPlants.push(plant);
}
}
And as a suggestion, you can even wrap the logic to create a new plant inside a method, like this:
var myPlants = new Array();
var plantsInc = 5;
function createPlants()
{
reproducePlants();
setInterval(reproducePlants, 5000);
}
function createPlant()
{
var rr = Math.round(Math.random() * 150);
var gg = Math.round(Math.random() * 255);
var bb = Math.round(Math.random() * 150);
var plant = new Object();
plant.x = Math.random() * canvas.width;
plant.y = Math.random() * canvas.height;
plant.rad = 2;
plant.skin = 'rgba('+rr+','+gg+','+bb+', 1)';
return plant;
}
function reproducePlants()
{
// Push N new plants on the array.
for (var i = 0; i < plantsInc; i++)
{
myPlants.push(createPlant());
}
}
You are overriding all the existing values so instead of using myPlants[i] = plant; use myPlants.push(plant)
You'll want to modify your function to add a plant onto an existing array, rather than looping over your array and assigning it new values.
if you want to add a new value to your array every 5 seconds, something like this should work:
var myPlants = new Array();
var plantSpawn = 0;
function createPlants() {
reproducePlants();
setInterval(reproducePlants, 5000);
}
function reproducePlants() {
var rr = Math.round(Math.random() * 150);
var gg = Math.round(Math.random() * 255);
var bb = Math.round(Math.random() * 150);
var plant = new Object();
plant.x = Math.random() * canvas.width;
plant.y = Math.random() * canvas.height;
plant.rad = 2;
plant.skin = 'rgba('+rr+','+gg+','+bb+', 1)';
myPlants.push(plant);
}
This just adds a new plant to the end of your array rather than assigning new values to your current array each time you call your function. From here you should be able to put that into a for loop if you wanted to add more plants than 1 at a time. each iteration of the loop will only add a single plan to your array.
I am implementing-w saving algorithm.
I implemented it and tested on small sets, works great. but when I input the large data, a problem occurs in the saving functions, which computes
c(i,j) = c(start,i) + c(start,j) - c(i,j)
where c(i,j) is the cost for traveling from i to j.
so I have to compute that first, but it turned out extremely big computations, I think it takes, since I have over 9000 locations in my data.
9000+8999+ ...... +1 = 50,000,000 (near to that)
steps.
here is my function to compute savings.
this.calc_savings=function()
{
var size = this.city_array.length; //number of cities: greater than 9000
var start =start_city_index;
for(var i=0; i < size; i ++)
{
if(i != start)
{
for(var j=i+1; j< size ; j++)
{
if(j !=start)
{
var dis1 = this.get_distance(start,i);
var dis2 = this.get_distance(start,j);
var dis3 = this.get_distance(j,i);
var cost = dis1 + dis2 - dis3;
var m_save = new saving(i,j,cost);
this.savings.push(m_save);
}
}
}
}
};
it is reporting heap out of memmory error.
And I find out that without
get_distance(...)
function, it works fast.
that function computes distance between two earth coordinates, as shown
function calcCrow(lat1, lon1, lat2, lon2)
{
var lati, latj, longi, longj;
var q1, q2, q3, q4, q5;
var m_pi = 3.14159265358979323846264;
lati = m_pi * lat1 / 180.0;
latj = m_pi * lat2 / 180.0;
longi = m_pi * lon1 / 180.0;
longj = m_pi * lon2 / 180.0;
q1 = Math.cos (latj) * Math.sin(longi - longj);
q3 = Math.sin((longi - longj)/2.0);
q4 = Math.cos((longi - longj)/2.0);
q2 = Math.sin(lati + latj) * q3 * q3 - Math.sin(lati - latj) * q4 * q4;
q5 = Math.cos(lati - latj) * q4 * q4 - Math.cos(lati + latj) * q3 * q3;
var dis_meter = (6378388.0 * Math.atan2(Math.sqrt(q1*q1 + q2*q2), q5) + 1.0);
return dis_meter / 1000;
};
which is called by
this.get_distance=function(first,next)
{
var first_city,next_city;
first_city = this.city_array[first];
next_city = this.city_array[next];
return Math.floor(calcCrow(first_city.x, first_city.y, next_city.x, next_city.y));
};
thes saving is defined as
var saving = function( x_int, y_int,value)
{
this.x =x_int ; //latitude
this.y =y_int ; //longitude
this.value = value;
};
so,what should I do?
Any suggestions?
You can reduce the amount of calls to get_distance a lot, by simply caching the results, since I assume that these Values don't change during one loop.
this.calc_savings = function(){
var size = this.city_array.length; //number of cities: greater than 9000
var startDistances = this.city_array.map((city,i) => i === start_city_index? 0: this.get_distance(start_city_index, i));
for(var i=0; i < size; ++i){
if(i === start_city_index) continue;
var dis1 = startDistances[i];
for(var j=i+1; j<size; ++j){
if(j === start_city_index) continue;
var dis2 = startDistances[j];
var dis3 = this.get_distance(j, i);
var cost = dis1 + dis2 - dis3;
this.savings.push(new saving(i, j, cost));
}
}
};
maybe you can even cache startDistances as long as start_city_index doesn't change; that would reduce the cost to compute even more.
If you include your implementation of get_distance and new saving(), there could be even more improvements possible.
Edit: I just realized that we're talking about cities, and that they don't move that much ;) so the distances are pretty static. You can precompute them once and cache em all; that's not even a big overhead, since you already have to do this in a single call to calc_savings. This would reduce your cost to call get_distance to a single lookup at an Array. Although, it might have quite a memory impact (9000 values -> 40495500 possible combinations -> ~155MB to store that many ints)
//Beware, code is untested
this.init_cache = function(){
var rad = Math.PI / 180;
var size = this.city_array.length;
var _distances = this._distances = Array(size * (size-1) / 2);
var _offsets = this._offsets = Array(size);
for(var i = 0, k = 0; i<size; ++i){
_offsets[i] = k;
var a = this.city_array[i],
lat1 = a.x * rad,
lon1 = a.y * rad;
for(var j = i+1; j<size; ++j){
var b = this.city_array[j],
lat2 = b.x * rad,
lon2 = b.y * rad,
q1 = Math.cos(lat2) * Math.sin(lon1 - lon2),
q3 = Math.sin((lon1 - lon2)/2),
q4 = Math.cos((lon1 - lon2)/2),
q2 = Math.sin(lat1 + lat2) * q3*q3 - Math.sin(lat1 - lat2) * q4*q4,
q5 = Math.cos(lat1 - lat2) * q4*q4 - Math.cos(lat1 + lat2) * q3*q3,
dist = 6378388 * Math.atan2(Math.sqrt(q1*q1 + q2*q2), q5) + 1;
_distances[k++] = Math.floor( dist / 1000 );
}
}
};
this.get_distance = function(i, j){
if(i === j) return 0;
if(j < i) i^=j, j^=i, i^=j; //swap i and j
this._distances || this.init_cache(); //just ensuring that cache is initialized when using it.
return this._distances[ this._offsets[i] + j-i-1 ]
};
this.calc_savings = function(){
var size = this.city_array.length;
for(var i = 0; i < size; i ++){
if(i === start_city_index) continue;
var dis1 = this.get_distance(start_city_index,i);
for(var j = i+1; j < size; j++){
if(j === start_city_index) continue;
var dis2 = this.get_distance(start_city_index,j);
var dis3 = this.get_distance(j,i);
var cost = dis1 + dis2 - dis3;
this.savings.push(new saving(i,j,cost));
}
}
};
Say I have an array in this format:
var arr = [{lat: 123.123, lng: 321.321}, {lat: 567.567, lng: 765.765}]
Based on some map coordinates, how can I most effectively find the object with coordinates closest to the map coordinates?
A naive solution is to do:
var getClosestPoint = function(coord, coordArray) {
var bestDistance = null;
var bestCoord = null;
for (var i = 0; i < coordArray.length; ++i) {
var currentCoord = coordArray[i];
var distance = getDistance(coord, currentCoord);
if ((bestDistance == null) || (distance < bestDistance)) {
bestDistance = distance;
bestCoord = currentCoord;
}
}
return {'distance': bestDistance, 'coord':bestCoord};
};
// Based on the solution here:
// http://stackoverflow.com/questions/365826/calculate-distance-between-2-gps-coordinates
var getDistance = function(coordA, coordB) {
var R = 6371; // km
var dLat = (coordB.lat-coordA.lat).toRad();
var dLon = (coordB.lng-coordA.lng).toRad();
var lat1 = coordA.lat.toRad();
var lat2 = coordB.lat.toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d;
};
In other words, the naive solution is to just iterate through all the points, updating the current best distance and the corresponding coordinate. If your list of points is small, this may be reasonable to do. However, a more effective solution is to use a tree structure, where each internal node in the tree is represented by the mean coordinate of all points under that node. You then search the tree by descending the node with the closest mean coordinate until you reach a leaf. This approach allows you to throw out a larger number of candidate points in each iteration, giving a logarithmic solution.
In other words, a more effective solution looks like:
var getClosestPoint = function(coord, coordNode) {
var children = coordNode.getChildren();
if (children.length == 0) {
return coordNode.getCenterCoord();
}
var closestChild = null;
var bestDistance = 0.0;
for (var i = 0; i < children.length; ++i) {
var currentCoord = children[i].getCenterCoord();
var distance = getDistance(coord, currentCoord);
if ((closestChild == null) || (distance < bestDistance)) {
closestChild = children[i];
bestDistance = distance;
}
}
return getClosestPoint(coord, closestChild);
}
Of course, this assumes that you've built up such a tree in the first place. If you are running "getClosestPoint()" repeatedly with the same set of points, then it is probably worthwhile to build up such a structure (if you only execute "getClosestPoint()" once for any given set of points, then the naive solution may be reasonable). The articles on K-D trees and quad trees may be of interest for further reading on this general approach and how to build up and partition the points into these trees.
I believe this should work on a square grid. If the values reset after a certain point, like on earth, there needs to be some adjustment to this solution.
function calculateDistance(x1, x2, y1, y2){
return Math.sqrt(Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2));
}
var retrievedCoords = {lat: 12234, lng: 135};
var closestPoint = arr[0];
var distanceToClosestPoint = calculateDistance(retrievedCoords.lat, arr[0].lat, retrievedCoords.lng, arr[0].lng);
for (var i = 1; i < arr.length; i++){
var tempDist = calculateDistance(retrievedCoords.lat, arr[i].lat, retrievedCoords.lng, arr[i].lng);
if (tempDist > distanceToClosestPoint){
closestPoint = arr[i];
distanceToClosestPoint = tempDist;
}
}
I really try to find out why the for loop is looping again and again. My question is why is the first for looping again and again thought x is 1?
The result shows random counts of progressbars with a random progresses (img element is the progress). But it should only show 1 because x is 1. Can somebody tell me whats the answer?
function progress(){
var min = 0;
var max = 10;
/*var x = Math.floor(Math.random() * (max - min)) + min;*/
var x = 1;
var main_div = document.createElement('div');
main_div.className = "main_div";
document.body.appendChild(main_div);
for(var i = 0; i < x; i++){
var einfuegen = document.createElement('div');
einfuegen.className = 'statusbar';
main_div.appendChild(einfuegen);
var einfuegen2 = document.createElement('img');
einfuegen2.id = 'bild';
einfuegen2.name = 'bild';
einfuegen2.src = 'project_status.gif';
var zielort = document.getElementsByClassName('statusbar')[i];
zielort.appendChild(einfuegen2);
var min = 0;
var max = 100;
var x = Math.floor(Math.random() * (max - min)) + min;
document.getElementsByTagName('img')[i].style.width = x+"%";
}
}
You need to use some different names for variable in loop
var min = 0;
var max = 100;
var x = Math.floor(Math.random() * (max - min)) + min;
it should be
var min1 = 0;
var max1 = 100;
var x1 = Math.floor(Math.random() * (max1 - min1)) + min1;
As you are using x in loop condition and modifying it inside loop, causing malfunction of loop.
You're changing x here:
var x = Math.floor(Math.random() * (max - min)) + min;
So the loop will loop a random number of times between 0 and 100.
Use a different variable name for the value of your progress bar, and for that matter, the max and min values of the progress bar:
var value = Math.floor(Math.random() * (maxValue - minValue)) + minValue;
document.getElementsByTagName('img')[i].style.width = value+"%";
This confusion is the very reason why JSLint recommends declaring all of your variables at the top of your function:
function progress(){
var min = 0,
max = 10,
x = 1,
i,
main_div = document.createElement('div'),
einfuegen,
einfuegen2,
zielort,
minValue = 0,
maxValue = 100,
value;
// rest of function...
}
The variable list above is very long because it has the values for both the outside of the loop and the inside of the loop. The solution to this is to factor your code out into separate functions:
function progress(){
var min = 0,
max = 10;
x = 1,
main_div = document.createElement('div'),
i;
main_div.className = "main_div";
document.body.appendChild(main_div);
for(i = 0; i < x; i += 1){
mainDiv.appendChild(makeProgressBar());
}
}
function makeProgressBar() {
var einfuegen = document.createElement('div'),
einfuegen2 = document.createElement('img'),
min = 0,
max = 100,
x = Math.floor(Math.random() * (max - min)) + min;
einfuegen.className = 'statusbar';
einfuegen2.id = 'bild';
einfuegen2.name = 'bild';
einfuegen2.src = 'project_status.gif';
einfuegen.appendChild(einfuegen2);
einfuegen2.style.width = x+"%";
return einfuegen;
}
This will also help to prevent variable name collisions.
x starts as 1 but you change it in the loop like this:
var x = Math.floor(Math.random() * (max - min)) + min;
which returns a number between 0-100 and the loop continues until it reaches above the random number.