Demanding multiple coordinates from an undefined amount of elements - javascript

Firstly I would like to give you an example, of what exactly I am talking about, and afterwards what I found out/different problems.
I would like to ask for every element, here points (they do share a class) with a diameter of 1 px. To simplify it, I thought of putting it inside an array. The amount of these points is undefined, there may be 2 or 100.
Afterwards i would like to store the x and y coordinates, which I get with the getBoundingClientRect() function, inside a new array. In which I would use every first for x and every second for y.
Now do not confuse this with the position within the array, I would like to know how I can "convert" the element from a query so I can use the getBoundingClientRect() function.
I hope this is all the information needed. I myself researched on here, but I could not find anything that was near my (rather big) demand.
I do not have any code, which I think would be useful.

I have found a solution myself. It is definitely not the smoothest nor the fastest solution, but it works.
for(iAllPoints=0;iAllPoints<(aPoints-1);iAllPoints++)
{
//Creating necesarry variables and asking for the needed data from CSS
var sPointPos = document.querySelector(".startPoint").getBoundingClientRect();
var tarPoints = document.querySelector(".target");
var AOfTarPoints = document.getElementsByClassName("target").length;
var calculatedDistances = [];
//Demanding all coordinates from each target point. Aswel as calculating the distance
if (iAllPoints!=(aPoints-2))
{
for(i = 0;i<AOfTarPoints;i++)
{
tarPoints = document.querySelector(".target");
//Calculating
var SideA = sPointPos.top - tarPoints.getBoundingClientRect().top;
var SideB = sPointPos.left - tarPoints.getBoundingClientRect().left;
var CEPDistance = Math.sqrt(Math.pow(SideA,2)+Math.pow(SideB,2));
calculatedDistances[i] = CEPDistance;
tarPoints.classList.add("inCalculation");
tarPoints.classList.remove("target");
}
minimum = Math.min.apply(Math,calculatedDistances);
var smallestDistance = document.querySelector(".inCalculation");
document.querySelector(".startPoint").classList.add("used");
document.querySelector(".startPoint").classList.remove("startPoint");
smallestDistance.classList.add("startPoint");
smallestDistance.classList.remove("inCalculation");
//Reseting the left unused points for next point
document.querySelector(".inCalculation").classList.add("target");
document.querySelector(".inCalculation").classList.remove("inCalculation");
finalDistance += minimum;
}
else
{
for(i = 0;i<AOfTarPoints;i++)
{
tarPoints = document.querySelector(".target");
//Calculating
var SideA = sPointPos.top - tarPoints.getBoundingClientRect().top;
var SideB = sPointPos.left - tarPoints.getBoundingClientRect().left;
var CEPDistance = Math.sqrt(Math.pow(SideA,2)+Math.pow(SideB,2));
calculatedDistances[i] = CEPDistance;
tarPoints.classList.add("inCalculation");
tarPoints.classList.remove("target");
}
minimum = Math.min.apply(Math,calculatedDistances);
var smallestDistance = document.querySelector(".inCalculation");
document.querySelector(".startPoint").classList.add("used");
document.querySelector(".startPoint").classList.remove("startPoint");
smallestDistance.classList.add("used");
smallestDistance.classList.remove("inCalculation");
finalDistance += minimum;
}
I haven't given every single Variable, but you should be able to understand it either way.

Related

How can I get the particular point in a THREE.Points object to change his position?

I work on a personal project to try out equations to try to simulate the behavior of a galaxy. I have so far managed to place the Points as I wanted, but now I want to take each point individually to change its position.
The goal for now is just to successfully try to apply a Random Vector to each of the points.
I tried:
var direction = new THREE.Vector3(0.00003, 0.000005, 0);
points.position.add(direction);
but this applies to all Points.
Then I tried something like that:
for (let i = 0; i < points.geometry.attributes.position.count; i++) {
points.geometry.attributes.position[i] = Math.random() * 500
}
points.geometry.attributes.position.needsUpdate = true;
But nothing append :( I thing I missed something but I dind't know what
Here the full code on codepen:
Codepen
When you access:
points.geometry.attributes.position[i]
you're not getting the array of the vertex positions. You're getting the BufferAttribute. What you probably want is the array inside the BufferAttribute:
points.geometry.attributes.position.array[i]
However, this is still not the recommended approach. Three.js recommends you use the .getAttribute() method:
// Get the attribute
const posAttribute = points.geometry.getAttribute("position");
// Get the array inside the attribute
const posArray = posAttribute.array;
// Increment by 3 at a time to access XYZ separately
for(let i3 = 0; i3 < posArray.length; i3 += 3) {
posArray[i3 + 0] = xPosition;
posArray[i3 + 1] = yPosition;
posArray[i3 + 2] = zPosition;
}
// Tell the attribute it needs updatin
posAttribute.needsUpdate = true;

Dynamic variable declaration. Is this even the right method?

A little new to JS so be gentle :)
I'm trying to create a program that holds 5000+ boolean values that dynamically change based on other vars.
const chars = "abcdefghijklmnopqrstuvwxyz0";
const charsC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0"
const maxNum = 48;
const maxTile = 6;
var tile1, tile2, tile3, tile4, tile5, tile6
// test vars
var tile4 = "A27"
var t4a27 = false
// this snippet will be in an interval loop
for (let i = 1; i <= maxTile; ++i) {
for (let n = 0; n < chars.length; ++n) {
for (let j = 1; j <= maxNum; ++j) {
// this obviously doesnt work
var t[i][`${chars[n]}`][j];
// ^ ^ ^
if (tile[i] == `${charsC[n]}${j}`) {
t[i][h][j] = true;
console.log(t4a27)
} else {
t[i][h][j] = false;
}
}
}
}
For clarification a better word than "tile" for the vars could be "sprite" rather because its a point on the sprite.
The basic concept is the tile vars are designed to output their current position as a string value e.g. "A27". Then this loop will take that information and scan each tile subset to be true/false. So if the sprite lower right quadrant is inside "A27" the output would be t4a27 = true
In practice I can do this with just a lot of code (over 20,000 lines) but I figured their has to be an easier way that requires far less code.
This is probably not the right approach for your problem.
If you really need to store this amount of variables, it is probably best to put them in an object like so:
var tiles = {}
var tileName = 'abc'
// Dynamic setting:
tile[tileName] = true
// Dynamic reading:
console.log(tile[tileName])
I am wondering if you really want to store 5000 variables or if there is another way to calculate them at the time you need time, but that requires a bit more knowledge of the problem.
Javascript doesn't have this kind of ability to reflect local variables.
What you can do is attach all those variables to a global object, and proceed with: Object.keys(your_object) and your_object[key_name_here] = ...
I think you should use a 2-dim array for this. Or use a regular array of booleans with the appropriate size and do the index-magic yourself.
As you said, you are running on coordinates. A-27 is the same as row(1)+field(27) -- considering A is 1
If your field is 500x100, you create an Array as such: let gamefield = Array(500*100);
Warning: I have not tested this for syntax errors, but you should get the idea.
let gamefield = Array(500*100);
// optional gamefield.fill(true);
let row = idx => idx * 500;
let posIdx = (r, c) => row(r) + c;
// there is a sprite with a tiles property that returns
// 4 index positions for the sprite's quadrants as [r,c]
let quadrants = sprite.tiles.reportPositions()
// filter the quadrants where the gamefield at r,c is true
// this might also be a good case for some() instead of filter()
let collisions = quadrants.filter(pos => return gamefield[posIdx(...pos)]);
// if there is any of these, you can kill the sprite.
if(collisions.length > 0) sprite.kill();

Swapping images in Javascript

finally started with JS and I have a question.
Why doesn't this code work (I have two images with fir and sec Ids in HTML)
function swap() {
let x = document.getElementById("fir").src
let y = document.getElementById("sec").src
let z = x
x = y
y = z
}
But this one does
function swap() {
let x = document.getElementById("fir")
let y = document.getElementById("sec")
let z = x.src
x.src = y.src
y.src = z
}
It's because document.getElementById("fir").src returns the path of the image (string) whereas in the second case you are manipulating the DOM (reference). you can console log or apply break point the output in both cases and check what's happening.
The reason the first one doesn't work is that while you have swapped the elements that your variables point to, you haven't changed the elements themselves. There are a couple of ways of swapping the elements (one of which you already posted and test)
Swap source fields
Swap outerHTML (z = x.outerHTML; x = y.outerHTML; y = z.outerHtML)
Move the actual elements (z = x.nextSibling; y.parentNode.insertBefore(x,y); z.parentNode.insertBefore(y,z);
Example 3 actually is incomplete: You'd also need to handle the case where there's no nextSibling. But hopefully this gives you more perspective of what attempt 1 and 2 are doing as well as how to change and manipulate elements

find the least value in a array in angularjs

I'm trying to show the nearest branch location in a map.SO i want to get the branch which has the least difference between the current location and the branch location. i have taken the differenec like this.
for(var i=0;i<$scope.locations.BranchAndAtms.length;i++){
var mapObject = $scope.locations.BranchAndAtms[i];
var differenceLat = (mapObject.lat - c.latitude);
var differenceLon = (mapObject.lon - c.longitude);
var Difference = (differenceLat + differenceLon);
alert(Difference );
Now i get the difference between every branch in my array.how to take the value with the least difference.
NOTE: difference i get comes in minus as well as positive values.
Outside of your for loop, you'll want to declare a variable that is going to keep track of which array index has the lowest value and another for what the lowest value currently is. By default, it will store the very first item as the lowest - this comes in handy if there is only one item in your array.
var lowest_index = 0;
var lowest_value = 0;
Inside of your for loop, you'll want to take the absolute values of the differences.
for...
var differenceLat = Math.abs(mapObject.lat - c.latitude);
var differenceLon = Math.abs(mapObject.lon - c .longitude);
Now, compare the existing lowest value to the current one, and if the current is lower, set lowest to that value of i.
if(Difference < lowest_value) {
lowest_index = i;
lowest_value = Difference;
}
So, your code should look like:
var lowest_index = 0;
var lowest_value = 0;
for(var i=0;i<$scope.locations.BranchAndAtms.length;i++){
var mapObject = $scope.locations.BranchAndAtms[i];
var differenceLat = Math.abs(mapObject.lat - c.latitude);
var differenceLon = Math.abs(mapObject.lon - c.longitude);
var Difference = (differenceLat + differenceLon);
if(Difference < lowest_value) {
lowest_index = i;
lowest_value = Difference;
}
}
In addition to Steve's answer, I'd recommend taking a look at how to correctly calculate distances between locations: Calculate distance between two latitude-longitude points? (Haversine formula)
So, create a function for calculating the distance:
function calculateDistance(currentLocation, branchLocation) {
/* the actual implementation, use answers from
* https://stackoverflow.com/questions/27928/ as reference
*
* Note that if you want, you could also use the actual latitude
* and longitude values as parameters for this function:
* calculateDistance(currentLat, currentLon, branchLat, branchLon)
*/
return distance;
}
And then use it inside the for-loop instead of the current difference calculations:
var Difference = calculateDistance(c, mapObject);
// or if you want to have the separate latitude and longitude parameters:
// var Difference = calculateDistance(c.latitude, c.longitude, mapObject.lat, mapObject.lon);
Otherwise Steve's approach is valid to follow.
(If you'd like to show for example all branch locations within given distance, or all the nearest branch locations if there are more than one branch with exactly the same distance, you'll need to store the distances and sort by them. But this goes out of the topic, as you did want to show only one branch location.)

In box2dweb how to destroy created body

I create bodies at mouse click with this pretty standard way in box2dweb:
*stage.onMouseDown = function(){
var fixDef = new box2d.b2FixtureDef;
fixDef.density = 1;
fixDef.friction = 0.5;
fixDef.restitution = 0.7;
var bodyDef = new box2d.b2BodyDef();
bodyDef.type = box2d.b2Body.b2_dynamicBody;
bodyDef.position.x = mouseX /scale;
bodyDef.position.y = mouseY /scale;
fixDef.shape = new box2d.b2CircleShape(Math.random()*100/scale);
world.CreateBody(bodyDef).CreateFixture(fixDef);}
I really don't know how to insert a name or an Id for my created bodies (eventually I can add a var num++ at every creation). Also, I don't know how to get back my body through the id and call the method .DestroyBody to delete it specifically.
I'm at early stages with JavaScript and Objective C so methods and docs made for Actionscript make me nuts..
Thanks in advance.
Question update:
I found a way to get back my already created object, finding the one i want among all of them using this way:
note: myBody is global
myBody['enter'+prodNum] = bodyDef;
bodyDef.userData = prodNum;
myBody['enter'+prodNum].id = bodyDef.userData;
prodNum is a global var which has a "++" at every cycle. With this i can recall my body back using both the body's var name and the bodyDef.userData property.
with the following function, called in my init() that's executed through window.onload, i can, as console.log shows, change what i want of my retrieved body, however no changes are applied to the body in canvas, even if its property in log resulted modified i cannot notice any change on the screen.
function reduceObj(){
var itsMe;
itsMe = myBody.enter10;
var newPosX = itsMe.position.x;
itsMe.active = false;
itsMe.awake = true;
itsMe.linearVelocity.x = 2000;
itsMe.position.x = newPosX+500;
itsMe.fixedRotation=true;
itsMe.allowSleep=true;
console.log(myBody.enter10,itsMe,itsMe.id,'it s me');
}
Cannot get why all this happens.. plus i already set the step() function which should refresh my world every x milliseconds... Help pls
The CreateBody function should return a reference you can keep, to destroy the body later.
var mybody = CreateBody( bodyDef );
mybody.CreateFixture( fixDef );
You can't just set properties in a body to change it, you need to use the appropriate functions:
// later...
mybody.SetActive( false );
mybody.SetAwake( true );
var vel = mybody.GetLinearVelocity();
vel.x = 2000;
mybody.SetLinearVelocity( vel );
var pos = mybody.GetPosition();
pos.x += 500;
mybody.SetPosition( pos );
mybody.SetFixedRotation( true );
mybody.SetSleepingAllowed( true );
Please keep in mind that 500 units is half a kilometer, so that's probably not what you would want to be doing. Use meters for your dimensions, not pixels. A velocity of 2000m/s is around 7200km/h or mach 6 (as reference the fastest aircraft ever built does about mach 8, so this is also most likely not what you want). Take a look at this page for some other common gotchas: http://www.iforce2d.net/b2dtut/gotchas

Categories