I'm having trouble with a small algorithm - javascript

Imagine I have a number of objects represented as balls in a gravity simulation, they're clumped together in 3 groups (for example, but it could be any number), how can give each object value depending on which group (1,2,3) it's in?
I only got this far, I can't figure it out...
var objects = [/* the balls */];
...
this.objects.forEach(
function(one) {
this.objects.forEach(
function(two) {
if(distance(one, two) <= 0) {
// these two are in the same group
}
}
);
}
);
The thing is, two balls in the same group might not necessarily be touching because there may a another ball in between them, but all balls in a group touch at least one other ball in the group.
The value would just be something like "this.group = 1;".
Any ideas are much appreciated, thanks.

Your problem is that you cannot disambiguate balls from which group it came from.
Try using three arrays to represent the three groups, or a more object-like structure that can reference which group the balls come from.

Related

Group nodes which are visually together

I am implementing force-directed graph in d3js.
I want to divide my graph into two halves and colour both the halves with different colour, after the network has been rendered and forceSimulation has completed.
What I am looking for is explained in image.
I am refering here.
I don't want to update the group field into my data as described in the link because my links are changing dynamically on several events which is also changing the orientation of the network and updating group field into the data is creating the groups of same nodes whether they are near or far from each other.
Currently, I am using the window coordinates to divide this.
const screenWidth = window.screen.availWidth;
const halfScreen = screenWidth / 2;
nodes.selectAll().attr("fill", function (d) {
return d.x < halfScreen ? "blue" : "green";
});
But this is not the good idea. I would love to know any other way that is possible to do this.
So, my, interpretation of your question: you want to divide the nodes into two groups. Preferably each with half of the nodes, in which the distances between the nodes in each group is as small as possible.
The best algorithms for this that I know of are algorithms for constructing a "minimum spanning tree", for example, Kruskal's algorithm.
Adapting the algorithm to your problem, you start with (a copy of) the graph, having no edges. You then add the edges, sorted by length, smallest first. You stop doing this as soon as you have exactly two connected components. These connected components form groups in which nodes have a small mutual distance.
However, the groups probably won't have the same number of nodes, and I don't guarantee that this gives you the smallest mutual distance.
EDIT:
If there is more than 1 connected component, you could group them by starting with two empty groups and repeatedly adding a component (largest first) to the group that has the smallest number of nodes. This will probably give you more or less equal groups.

3D Grid for multiple shapes

A few months ago I made a small terrain generator, like Minecraft, for a school project.
The way I did this was by using multiple chunks. Each chunk contained a 3-dimensional array that stored the blocks.
Every position in this array corresponded with the position of the block it contained.
blocks[x, y, z] = new Block();
Now I would like to add different sizes if blocks. However, I can't do that with the way I am storing the blocks right now, because bigger blocks would have to be spread over multiple positions in the 3-dimensional array.
An example of a game with different sizes of blocks (and different shapes) is LEGO Worlds. How does a game like this store all these little blocks?
I hope someone can help me with this.
The language I am using is Javascript in combination with WebGL.
Thanks in advance!
In my experience there are a few different ways of tackling an issue like this, but the one I'd recommend would depend on the amount of time you have to work on this and the scope (how big) you wanted to make this game.
Your Current Approach
At the moment I think your using what most people would consider the most straightforward approach by storing the voxels in a 3D grid
[Source].
But two problems you seem to be having is that there isn't an obvious way to create blocks that are bigger then 1x1 and that a 3D grid for a world space is fairly inefficient in terms of memory usage (As for an array you have to have memory allocated for every cell, including empty space. JavaScript is no different).
An Alternative Approach
An alternative to using a 3D array would be to instead use a different data structure, the full name being a sparse voxel octree.
This to put it simply is a tree data structure that works by subdividing an area of space until everything has been stored.
The 2D form of this where a square sub divides into four smaller quadrants is called a quad tree and likewise a 3D equivalent divides into eight quadrants, called an octree. This approach is generally preferable when possible as its much more efficient because the trees only occupy more memory when its absolutely essential and they can also be packed into a 1D array (Technically a 3D array can be too).
A common tactic used with quad/octrees in some block based games is to take a region of the same kind of voxel that fit into one larger quadrant of the tree is to simply stop sub division there, as there's no reason to go deeper if all the data is the same.
The other optimization they can make is called sparse where regions of empty space (air) are simply deleted since empty space doesn't do anything special and its location can be inferred.
[SVO Source]
[Z Order Curve Source]
Recommended Approach
Unless you have a few months to complete your game and you're at university I seriously wouldn't recommend an SVO (Though reading up about could impress any teachers you have). Instead I'd recommend taking the same approach that Minecraft appears to visibly has. E.G. A door is 1X2 but blocks can only be 1x1, then just make it two blocks.
In the example of a door you would have four unique blocks in total, two for the upper and lower half, and two variations of each being opened or closed.
E.G.
var cubeProgram; // shader program
var cubeVBO; // vertex buffer (I recommend combining vertex & UV coords)
var gl; // rendering context
// Preset list of block ID's
var BLOCK_TYPES = {
DOOR_LOWER_OPEN: 0,
DOOR_UPPER_OPEN: 1,
DOOR_LOWER_CLOSED: 2,
DOOR_UPPER_CLOSED: 3,
}
var BLOCK_MESHES = {
GENERIC_VBO: null,
DOOR_UPPER_VBO: null
DOOR_LOWER_VBO: null
}
// Declare a Door class using ES6 syntax
class Door {
// Assume X & Y are the lower half of the door
constructor(x,y,map) {
if (y - 1 > -1) {
console.error("Error: Top half of the door goes outside the map");
return;
}
this.x = x;
this.y = y;
map[x][y ] = BLOCK_TYPES.DOOR_LOWER_OPEN;
map[x][y-1] = BLOCK_TYPES.DOOR_UPPER_OPEN;
}
}

Grouping shapes in paper.js

Trying out paper.js for the first time, working on some generative visuals. Trying to figure out the best route to accomplish the following:
Each cloud shape is individual, but when they intersect each other, I want them to compound into one larger cloud.
Within that larger cloud, I want the individual shape to retain it's properties, so that it can eventually detach and become a single cloud again.
So I am running into a few problems trying to accomplish this. I check for intersections:
//cloudArray refers to an array of path items
Cloud.prototype.checkIntersection = function() {
//loop through all existing cloud shapes
for(var i=0;i<cloudArray.length;i++){
//avoid checking for intersections on the same cloud path
if(this.path !== cloudArray[i].path){
//if path intersects another, group the two, and
//sort them in the order of their id
if(this.path.intersects(cloudArray[i].path)){
tmpGrp = [this.path,cloudArray[i].path];
tmpGrp.sort(function(a,b){return a.id - b.id});
groupClouds(tmpGrp);
}
}
}
}
Now after intersections are checked, I attempt to group the clouds together into arrays:
function groupClouds(tmpGrp){
if(grps.length > 0){
for(var i=0;i<grps.length;i++){
if(tmpGrp !== grps[i]){
console.log('doesnt match');
grps.push(tmpGrp);
}else{
console.log('matches');
}
}
}else{
grps[0] = tmpGrp;
}
console.log(grps);
}
Now I know that I can't compare arrays this way, so I have tried to use the solution given here, but I didn't want to further clutter this question.
Is this method reasonable? I know that I could create a new compoundPath if I could create arrays for each group. The problem is assuring that each collection of intersecting clouds is correct, and that they are being updated efficiently.
Any advice?

How to generate level for a laser game in Javascript?

I am trying to generate a random level for my silly game. The game consists of having laser/detector pairs around a square field of possible mirrors. Like this:
/*
LLLLLLLLLL
LmmmmmmmmL
LmmmmmmmmL
LmmmmmmmmL
LLLLLLLLLL
*/
Now, I have an algorithm which generates a level, quite poorly, by relying on random placement, and rejecting bad positions. This is not very fast, and does not really generate the kind of fields I'd like to have. Please feel free to try it out at http://cmouse.desteem.org/laser/
Any suggestions are welcome.
The current algorithm looks something like this:
function createLevel:
for i=0 to mirrors:
mirrorLocation = pickRandomPosition
mirrorType = pickRandomType
if (verifyPosition(mirrorLocation, mirrorType)):
i = i - 1
next
else:
storeMirror(mirrorLocation, mirrorType)
In verifyPosition, we test the mirror that it reaches a laser in all four directions, in hope of avoiding undetectedable mirrors. It is somewhat boring code, so I omit it here.
One way to make sure it's not trying multiple fields more than once is to iterate over the fields and put a mirror or not based on some probability. The probability to put a mirror should be #mirros / #fields, so that the expected number of mirrors is #mirrors at the end.

Find in Multidiamentional Array

I have an multi dimensional array as
[
{"EventDate":"20110421221932","LONGITUDE":"-75.61481666666670","LATITUDE":"38.35916666666670","BothConnectionsDown":false},
{"EventDate":"20110421222228","LONGITUDE":"-75.61456666666670","LATITUDE":"38.35946666666670","BothConnectionsDown":false}
]
Is there any plugin available to search for combination of LONGITUDE,LATITUDE?
Thanks in advance
for (var i in VehCommLost) {
var item = VehCommLost[i];
if (item.LONGITUDE == 1 && item.LATITUDE == 2) {
//gotcha
break;
}
}
this is json string..which programming language u r using with js??
by the way try with parseJSON
Are the latitudes and longitudes completely random? or are they points along a path, so there is some notion of sequence?
If there is some ordering of the points in the array, perhaps a search algorithm could be faster.
For example:
if the inner array is up to 10,000 elements, test item 5000
if that value is too high, focus on 1-4999;
if too low, focus on 5001-10000, else 5000 is the right anwser
repeat until the range shrinks to the vicinity, making a straight loop through the remaining values quick enough.
After sleeping on it, it seems to me most likely that the solution to your problem lies in recasting the problem.
Since it is a requirement of the system that you are able to find a point quickly, I'd suggest that a large array is the wrong data structure to support that requirement. It maybe necessary to have an array, but perhaps there could also be another mechanism to make the search rapid.
As I understand it you are trying to locate points near a known lat-long.
What if, in addition to the array, you had a hash keyed on lat-long, with the value being an array of indexes into the huge array?
Latitude and Longitude can be expressed at different degrees of precision, such as 141.438754 or 141.4
The precision relates to the size of the grid square.
With some knowledge of the business domain, it should be possible to select a reasonably-sized grid such that several points fit inside but not too many to search.
So the hash is keyed on lat-long coords such as '141.4#23.2' with the value being a smaller array of indexes [3456,3478,4579,6344] using the indexes we can easily access the items in the large array.
Suppose we need to find 141.438754#23.2i7643 : we can reduce the precision to '141.4#23.2' and see if there is an array for that grid square.
If not, widen the search to the (3*3-1=) 8 adjacent grids (plus or minus one unit).
If not, widen to the (=5*5-9) 16 grid squares one unit away. And so on...
Depending on how the original data is stored and processed, it may be possible to generate the hash server-side, which would be preferable. If you needed to generate the hash client-side, it might be worth doing if you reused it for many searches, but would be kind of pointless if you used the data only once.
Could you comment on the possibility of recasting the problem in a different way, perhaps along these lines?

Categories

Resources