Sort an array by two fields - javascript

I'm trying to summarise this unordered 2d array:
[
[3.0, 1.0, 4.0],
[2.0, 1.0, 1.0],
[1.0, 1.0, 6.0],
[1.0, 1.0, 1.0],
[3.0, 2.0, 5.0],
[2.0, 2.0, 1.0],
[3.0, 1.0, 1.0],
[1.0, 1.0, 4.0],
[1.0, 2.0, 3.0],
[3.0, 1.0, 2.0],
[2.0, 1.0, 1.0],
[2.0, 2.0, 2.0]
]
I'm able to order it by the first then second columns like so:
[
[1.0, 1.0, 6.0],
[1.0, 1.0, 1.0],
[1.0, 1.0, 4.0],
[1.0, 2.0, 3.0],
[2.0, 1.0, 1.0],
[2.0, 1.0, 1.0],
[2.0, 2.0, 1.0],
[2.0, 2.0, 2.0],
[3.0, 1.0, 4.0],
[3.0, 1.0, 1.0],
[3.0, 1.0, 2.0],
[3.0, 2.0, 5.0]
]
Using this code:
function sortData(myArr) {
// sort on second column, asc
myArr.sort(function (element_a, element_b) {
return element_a[1] - element_b[1];
});
// sort on first column, asc
myArr.sort(function (element_a, element_b) {
return element_a[0] - element_b[0];
});
return myArr;
}
Ultimately, the result below is what I'm trying to get (sum of third column, grouped by 1st and 2nd in ascending order):
[
[1.0, 1.0, 11.0],
[1.0, 2.0, 3.0],
[2.0, 1.0, 2.0],
[2.0, 2.0, 3.0],
[3.0, 1.0, 7.0],
[3.0, 2.0, 5.0]
]

You can first sort your data and then use forEach() loop to group by first two elements and sum third element.
var data = [[3,1,4],[2,1,1],[1,1,6],[1,1,1],[3,2,5],[2,2,1],[3,1,1],[1,1,4],[1,2,3],[3,1,2],[2,1,1],[2,2,2]]
data.sort(function(a, b) {
return a[0] - b[0] || a[1] - b[1]
})
var result = [];
data.forEach(function(e) {
var key = e[0].toString() + e[1].toString();
if(!this[key]) result.push(this[key] = e.slice())
else this[key][2] += e[2]
}, {})
console.log(JSON.stringify(result))

Go through the sorted array, creating a new array of sums.
Create a new element when the 1st or the 2nd column become different, or add to the current element as long as those columns remain the same.

Using Array#reduce:
let arr = [
[3.0, 1.0, 4.0],
[2.0, 1.0, 1.0],
[1.0, 1.0, 6.0],
[1.0, 1.0, 1.0],
[3.0, 2.0, 5.0],
[2.0, 2.0, 1.0],
[3.0, 1.0, 1.0],
[1.0, 1.0, 4.0],
[1.0, 2.0, 3.0],
[3.0, 1.0, 2.0],
[2.0, 1.0, 1.0],
[2.0, 2.0, 2.0]
]
let res = Object.values(arr.reduce((a, c)=>{
let key = c.slice(0,2).join('|');
if(!a[key]){
a[key] = c
}else{
a[key][2] += c[2]
}
return a
},{})).sort((a, b)=>{
return a[0]-b[0] || a[1] - b[1]
});
console.log(JSON.stringify(res))
Basic theory is to use first 2 values to create an object key. If that key doesn't exist create a new one with current array as value.... if it already exists sum last value of each

Related

My webGL drawn cube has no outer layer and the part being lit up is the inside

The program that I am using draws the cube perfectly when there is no lighting applied to the color of it. When applied it looks like it doesn't have an outer layer and the outer parts are simply non-existent. The part that is being lit up is the inside of the cube and this is very visible in the output of the program.
I tried messing around with the code itself but it doesn't seem like that is the real problem here (I may be wrong), I also tried changing the values in the position, normal and indices vectors, however, this did not yield any results either.
These are the position, normal, and index values that are used:
var positions = new Float32Array([
// Front face
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// Back face
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// Top face
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
// Bottom face
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
// Right face
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
// Left face
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
]);
var normals = new Float32Array([
// Front
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
// Back
0.0, 0.0, -1.0,
0.0, 0.0, -1.0,
0.0, 0.0, -1.0,
0.0, 0.0, -1.0,
// Top
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
// Bottom
0.0, -1.0, 0.0,
0.0, -1.0, 0.0,
0.0, -1.0, 0.0,
0.0, -1.0, 0.0,
// Right
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
// Left
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0
]);
var indices = new Uint16Array([
0, 1, 2, 0, 2, 3, // front
4, 5, 6, 4, 6, 7, // back
8, 9, 10, 8, 10, 11, // top
12, 13, 14, 12, 14, 15, // bottom
16, 17, 18, 16, 18, 19, // right
20, 21, 22, 20, 22, 23, // left
]);
Sorry for the spam of code. I can provide any more that will be necessary. The output of the program.

gl.getBufferSubData not working with ArrayBuffer

I'm trying to read data from a buffer using gl.getBufferSubData, I followed the example from MDN
let position_buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, position_buffer);
let positions = [
-1.0, 1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, -1.0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
let arrBuffer = new ArrayBuffer(positions.length * Float32Array.BYTES_PER_ELEMENT);
gl.getBufferSubData(gl.ARRAY_BUFFER, 0, arrBuffer);
But I'm getting this error (both on Firefox and Chrome):
Uncaught TypeError: WebGL2RenderingContext.getBufferSubData: Argument 3 does not implement interface ArrayBufferView.

Plot.ly does not render when passed an array of traces

The code below fails to render data. No exceptions are thrown. However, the same code does work when given only one of the two traces as shown in the second code segment. The only difference is calling
Plotly.newPlot(target_target, traces); // doesn't render
instead of:
Plotly.newPlot(target_target, trace0); // trace1 also works.
I'm a javascript noob so it's probably something wrong with my traces array, but it looks like the example code I looked at.
Code that doesn't work (complete):
<html>
<head>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<div id='target' style="width:600px;height:450px;"></div>
<script>
var target_target = document.getElementById('target');
var trace0 =
[{
x: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
y: [0.5, 1.5, 6.5, 14.5, 25.5, 39.5],
type: 'scatter'
}];
var trace1 =
[{
x: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
y: [0.0, 1.0, 6.0, 14.0, 25.0, 39.0],
type: 'scatter'
}];
var traces = [ trace0, trace1 ];
Plotly.newPlot(target_target, traces);
</script>
</body>
</html>
Code that does work (complete):
<html>
<head>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<div id='target' style="width:600px;height:450px;"></div>
<script>
var target_target = document.getElementById('target');
var trace1 =
[{
x: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
y: [0.0, 1.0, 6.0, 14.0, 25.0, 39.0],
type: 'scatter'
}];
Plotly.newPlot(target_target, trace1);
</script>
</body>
</html>
The mistake you made was simply that the individual traces should be objects not array of a single object, all you need to do is to make this correction.
Before:
var trace0 =
[{
x: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
y: [0.5, 1.5, 6.5, 14.5, 25.5, 39.5],
type: 'scatter'
}];
After:
var trace0 =
{
x: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
y: [0.5, 1.5, 6.5, 14.5, 25.5, 39.5],
type: 'scatter'
};
Then these individual traces(objects) need to be grouped into an array and set in plotly.
var traces = [ trace0, trace1 ];
Plotly.newPlot(target_target, traces);
That is why the second example works, since the traces are received as an array of objects.
Please do refer the below example and check if your issue is resolved!
var target_target = document.getElementById('target');
var trace0 = {
x: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
y: [0.5, 1.5, 6.5, 14.5, 25.5, 39.5],
type: 'scatter'
};
var trace1 = {
x: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
y: [0.0, 1.0, 6.0, 14.0, 25.0, 39.0],
type: 'scatter'
};
var traces = [trace0, trace1];
Plotly.newPlot(target_target, traces);
<html>
<head>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<div id='target' style="width:600px;height:450px;"></div>
</body>
</html>

Is it possible to use the Javascript Array.prototype.filter() function with an array of other arrays?

In a Javascript code, I am using an array that contains other arrays. The array is actually four layers deep (There is an array with arrays of arrays of variables) and I need to remove some strings of a specific value from this array. I had seen the Array.prototype.filter() function and thought it would be useful, but I think it did not work because the strings were within other arrays. I cannot specifically address each sub-array though, for several reasons. Any suggestions for how to make it work or any alternatives would be welcome.
This is an example of a possible array created in my code:
[
[
[
[
1.0,
1.0,
1.0
],
[
0.0,
1.0,
1.0
],
[
1.0,
0.0,
0.0
],
[
1.0,
0.0,
0.0
],
[
1.0,
0.0,
1.0
],
[
t
]
],
[
[
0.0,
0.0,
1.0,
0.0,
0.0
],
[
1.0,
0.0,
1.0,
1.0,
0.0
],
[
1.0,
1.0,
0.0,
1.0,
0.0
],
[
1.0,
0.0,
0.0,
1.0,
1.0
],
[
0.0,
1.0,
0.0,
0.0,
0.0
],
[
1.0,
0.0,
1.0,
1.0,
0.0
],
[
1.0,
0.0,
0.0,
1.0,
0.0
],
[
t
]
],
[
[
0.0,
1.0,
1.0,
1.0,
0.0,
0.0,
1.0
],
[
0.0,
0.0,
0.0,
0.0,
1.0,
0.0,
0.0
],
[
1.0,
0.0,
0.0,
0.0,
1.0,
1.0,
0.0
],
[
1.0,
0.0,
0.0,
0.0,
0.0,
0.0,
1.0
],
[
1.0,
0.0,
1.0,
1.0,
1.0,
0.0,
0.0
],
[
t
]
],
[
[
0.0,
0.0,
0.0,
1.0,
1.0
],
[
0.0,
1.0,
1.0,
0.0,
1.0
],
[
1.0,
1.0,
1.0,
0.0,
1.0
],
[
t
]
],
[
[
t
]
]
],
[
[
[
1.0,
1.0,
0.0
],
[
0.0,
1.0,
1.0
],
[
1.0,
1.0,
0.0
],
[
0.0,
1.0,
0.0
],
[
1.0,
0.0,
1.0
],
[
t
]
],
[
[
0.0,
0.0,
1.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
1.0
],
[
1.0,
1.0,
1.0,
1.0,
1.0
],
[
1.0,
0.0,
0.0,
0.0,
1.0
],
[
1.0,
0.0,
0.0,
1.0,
0.0
],
[
0.0,
0.0,
1.0,
0.0,
1.0
],
[
1.0,
0.0,
1.0,
0.0,
0.0
],
[
t
]
],
[
[
0.0,
0.0,
1.0,
1.0,
1.0,
0.0,
1.0
],
[
1.0,
0.0,
0.0,
1.0,
1.0,
0.0,
0.0
],
[
1.0,
0.0,
1.0,
0.0,
0.0,
1.0,
0.0
],
[
0.0,
1.0,
1.0,
0.0,
0.0,
0.0,
1.0
],
[
1.0,
1.0,
1.0,
1.0,
0.0,
1.0,
0.0
],
[
t
]
],
[
[
1.0,
0.0,
0.0,
1.0,
0.0
],
[
0.0,
1.0,
1.0,
0.0,
0.0
],
[
0.0,
1.0,
1.0,
1.0,
0.0
],
[
t
]
],
[
[
t
]
]
],
[
[
[
0.0,
1.0,
0.0
],
[
1.0,
0.0,
0.0
],
[
1.0,
1.0,
0.0
],
[
1.0,
0.0,
0.0
],
[
1.0,
1.0,
0.0
],
[
t
]
],
[
[
1.0,
1.0,
0.0,
0.0,
1.0
],
[
1.0,
0.0,
0.0,
0.0,
1.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
1.0,
1.0,
1.0
],
[
1.0,
1.0,
0.0,
1.0,
0.0
],
[
0.0,
0.0,
1.0,
1.0,
0.0
],
[
0.0,
0.0,
1.0,
1.0,
0.0
],
[
t
]
],
[
[
1.0,
1.0,
1.0,
0.0,
0.0,
0.0,
1.0
],
[
1.0,
0.0,
1.0,
0.0,
1.0,
0.0,
1.0
],
[
0.0,
0.0,
0.0,
1.0,
1.0,
1.0,
0.0
],
[
1.0,
0.0,
0.0,
0.0,
1.0,
0.0,
1.0
],
[
1.0,
1.0,
1.0,
0.0,
1.0,
1.0,
1.0
],
[
t
]
],
[
[
1.0,
0.0,
1.0,
0.0,
1.0
],
[
1.0,
1.0,
1.0,
0.0,
1.0
],
[
1.0,
0.0,
0.0,
0.0,
0.0
],
[
t
]
],
[
[
t
]
]
],
[
[
[
t
]
]
]
]
I need to remove all of the "t" strings. This array is a bit smaller than it would normally be, and it will be a different size on each execution of the code. If it is unclear what I am asking, or if you thin it would be helpful, I can post the code, but it is a bit big so I don't want to clog up the page.
The array is actually four layers deep
You can use object destructuring to get the value of the fourth nested array
let res = arr.filter(([[[inner]]]) => typeof inner !== "string");

WebGL solid colors

https://www.dropbox.com/s/4zkhtdv4yaqhpxy/Screenshot%20from%202015-01-28%2010%3A42%3A02%201.png?dl=0
Can someone explain to me, what am I doing wrong? I want every face of the cube to have one solid colour. The code, which creates the cube, is in RunCube.coffee file and the vertices and colour are defined in Cube.coffee file. I think the problem is that I do not know, how to use indexes for colours.
Here is the repository on github https://github.com/trimpirim/shiny-soice
UPDATED:
I have Cube with all it's data.
#vertices: [
[ 6.89954888016507530, 0.39691390817415106, -4.02972512706645780],
[-0.78006682662096161, -3.78853119791598660, -7.00275139558893490],
[-5.79336942493284560, 3.47790796230961650, -4.28264251507835430],
[ 1.88624628185319150, 7.66335306839975420, -1.30961624655587690],
[ 0.78006682662096205, 3.78853119791598920, 7.00275139558893490],
[ 5.79336942493284290, -3.47790796230961740, 4.28264251507835780],
[-1.88624628185319150, -7.66335306839975150, 1.30961624655588270],
[-6.89954888016507440, -0.39691390817415328, 4.02972512706646220]
];
#faces: [
[0, 1, 2], [0, 2, 3],
[0, 3, 4], [0, 4, 5],
[0, 5, 6], [0, 6, 1]
[2, 1, 6], [2, 6, 7],
[2, 7, 4], [2, 4, 3],
[4, 7, 6], [4, 6, 5]
];
#colors: [
[1.0, 0.0, 0.0, 1.0],
[1.0, 1.0, 0.0, 1.0],
[0.0, 1.0, 0.0, 1.0],
[1.0, 0.5, 0.5, 1.0],
[1.0, 0.0, 1.0, 1.0],
[0.0, 0.0, 1.0, 1.0],
]
Can someone tell me, how should correct colours data look like?
EDIT:
There are not separated indices for colors. Indices are same for both, vertex positions and colors (or any other property you could think of).
To achive cube with 6 solid colors, you will have to repeat some parts of your arrays.
This is kind of prototype, how vertices look like:
vertices: [
{
position: [x,y,z],
color: [r, g, b, a]
},
{
position: [x,y,z],
color: [r, g, b, a]
},
...
];
Vertex with position: [0,0,0], color [1,0,0,1] is not same as vertex with position: [0,0,0], color [0,1,0,1]. You want one corner of cube be part of 3 faces with different color. So there must be 3 vertices in one corner with same position, but different color. Unfortunately in this case, position cannot be shared.
So your definition should look like this:
var vertex_positions = [
// see that front face and back face has 8 unique positions
// front face
[0, 0, 0],
[1, 0, 0],
[1, 1, 0],
[0, 1, 0],
// back face
[0, 0, 1],
[1, 0, 1],
[1, 1, 1],
[0, 1, 1],
// see that bottom face and top face has 8 unique positions too,
// but they repeated with different order from front and back
// bottom face
[0, 0, 0],
[1, 0, 0],
[1, 0, 1],
[0, 0, 1],
// top face
[0, 1, 0],
[1, 1, 0],
[1, 1, 1],
[0, 1, 1],
// left and right face have 8 unique positions too, but again
// repeated from front, back / bottom, top
// left face
[0, 0, 0],
[0, 1, 0],
[0, 1, 1],
[0, 0, 1],
// right face
[1, 0, 0],
[1, 1, 0],
[1, 1, 1],
[1, 0, 1]
];
Colors, same amount of elements as for positions:
var vertex_colors = [
// front face
[1.0, 0.0, 0.0, 1.0],
[1.0, 0.0, 0.0, 1.0],
[1.0, 0.0, 0.0, 1.0],
[1.0, 0.0, 0.0, 1.0],
// back face
[1.0, 1.0, 0.0, 1.0],
[1.0, 1.0, 0.0, 1.0],
[1.0, 1.0, 0.0, 1.0],
[1.0, 1.0, 0.0, 1.0],
// bottom face
[0.0, 1.0, 0.0, 1.0],
[0.0, 1.0, 0.0, 1.0],
[0.0, 1.0, 0.0, 1.0],
[0.0, 1.0, 0.0, 1.0],
// top face
[1.0, 0.5, 0.5, 1.0],
[1.0, 0.5, 0.5, 1.0],
[1.0, 0.5, 0.5, 1.0],
[1.0, 0.5, 0.5, 1.0],
// left face
[1.0, 0.0, 1.0, 1.0],
[1.0, 0.0, 1.0, 1.0],
[1.0, 0.0, 1.0, 1.0],
[1.0, 0.0, 1.0, 1.0],
// right face
[0.0, 0.0, 1.0, 1.0],
[0.0, 0.0, 1.0, 1.0],
[0.0, 0.0, 1.0, 1.0],
[0.0, 0.0, 1.0, 1.0],
];
Now indices:
var triangles = [
// front face
[0, 1, 2],
[0, 2, 3],
// back face
[4, 5, 6],
[4, 6, 7],
// bottom face
[8, 9, 10],
[8, 10, 11],
// top face
[12, 13, 14],
[12, 14, 15],
// left face
[16, 17, 18],
[16, 18, 19],
// right face
[20, 21, 22],
[20, 22, 23]
];
Cube is made of 12 triangles. With solid color faces, we need 4 unique vertices for 2 triangles, so we need 24 different vertex definitions.
This is the most traditional way as gman said. There are also other ways to achieve same effect, but theirs usecases are rare.
PS: sorry my indices might not be correct

Categories

Resources