Initialization of a struct array [duplicate] - c++

This question already has answers here:
How to initialize an array of struct in C++?
(3 answers)
Closed 5 years ago.
struct Sensors
{
int pin;
int angle;
bool state;
};
Sensors sensor[6];
How can I initialize every field of sensor like a normal array?
This method
mydata data[] = { { 1, 2, 3, 4, 5, 6 },
{ 0, 60, 120, 180, -120, -60 },
{ false, false, false, false, false, false} };
doesn't work, it returns me too many initialization.

You can use aggregate initialization.
struct Sensors
{
int pin;
int angle;
bool state;
};
Sensors sensor[6] = {
{ 0, 0, true },
{ 1, 0, true },
{ 2, 0, false },
{ 3, 0, false },
{ 4, 0, false },
{ 5, 0, false }
};

struct Sensors
{
int pin;
int angle;
bool state;
};
int main()
{
Sensors sensor[6] = {
{ 1, 2, false },
{ 1, 2, true },
{ 1, 3, false },
{ 2, 2, false },
{ -1, -2, true },
{ 1, 2, false }
};
return 0;
}

Related

chartjs horizontal bar chart get y position of each bar

I have a plugin which should render a circle for each value in the dataset at the same height as each bar is. I can get the y position for a value with
chart.scales.y.getPixelForValue(index)
but that is not the position of the bars.
const data ={
labels:[
"Macht",
"Ehre",
"Besitz",
[
"Selbst-",
"verwirklichung"
],
"Wettbewerb",
"Dienen",
"Spiritualität"
],
"datasets": [
{
"label": "first",
"backgroundColor": "rgb(208,55,25)",
"data": [
4,
8,
5,
4,
1,
1,
3
]
},
{
"label": "second",
"backgroundColor": "rgb(240,223,89)",
"data": [
1,
4,
5,
2,
5,
3,
3
]
}
]
}
const circles = {
id: 'circles',
afterDraw(chart, args, options) {
const {ctx, scales:{x,y}} = chart;
options.data.forEach((dataset) => {
let even = true
dataset.data.forEach((value,index) => {
var xpos = x.getPixelForValue(value);
var ypos = chart.scales.y.getPixelForValue(index) //HERE I WANT THE Y POSITION OF EACH BAR
ctx.save();
ctx.fillStyle = dataset.backgroundColor;
ctx.beginPath();
ctx.arc(xpos, ypos, 10, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.restore();
})
})
}
}
const chartOptions = {
maintainAspectRatio: false,
responsive:true,
indexAxis: 'y',
scales: {
x:{
min: 1,
max: 9,
},
y:{
ticks: {
stepSize: 1,
autoSkip: false,
},
min: 0,
max: 6,
position: 'left',
},
},
plugins: {
circles: {
data: [
{
"label": "Selbseinschätzung",
"backgroundColor": "rgb(208,55,25)",
"data": [
6,
4,
3,
7,
4,
4,
7
]
},
{
"label": "Selbseinschätzung",
"backgroundColor": "rgb(240,223,89)",
"data": [
7,
4,
4,
3,
6,
5,
2
]
}
]
}
}
}
const ctx = document.getElementById('mts').getContext('2d');
const myChart = new Chart(ctx, {
type: 'bar',
data: data,
options: chartOptions,
plugins: [circles]
});
[![enter image description here][1]][1]
How can I get the bars y position?
Now I have to give some more details, but I dont know how to explain the problem mor exactly. So I write this stuff.
I think you could use the dataset element for y.
const data ={
labels:["Macht", "Ehre", "Besitz", ["Selbst-", "verwirklichung"], "Wettbewerb", "Dienen", "Spiritualität"],
"datasets": [
{
"label": "first",
"backgroundColor": "rgb(208,55,25)",
"data": [4, 8, 5, 4, 1, 1, 3]
},
{
"label": "second",
"backgroundColor": "rgb(240,223,89)",
"data": [1, 4, 5, 2, 5, 3, 3]
}
]
}
const circles = {
id: 'circles',
afterDraw(chart, args, options) {
const {ctx, scales:{x,y}} = chart;
options.data.forEach((dataset, dsIndex) => {
const meta = chart.getDatasetMeta(dsIndex);
let even = true
dataset.data.forEach((value,index) => {
var xpos = x.getPixelForValue(value);
const elem = meta.data[index];
//var ypos = y.getPixelForValue(index) //HERE I WANT THE Y POSITION OF EACH BAR
var ypos = elem.y;
ctx.save();
ctx.fillStyle = dataset.backgroundColor;
ctx.beginPath();
ctx.arc(xpos, ypos, 10, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.restore();
})
})
}
}
const chartOptions = {
maintainAspectRatio: false,
responsive:true,
indexAxis: 'y',
scales: {
x:{
min: 1,
max: 9,
},
y:{
ticks: {
stepSize: 1,
autoSkip: false,
},
min: 0,
max: 6,
position: 'left',
},
},
plugins: {
circles: {
data: [
{
"label": "Selbseinschätzung",
"backgroundColor": "rgb(208,55,25)",
"data": [
6,
4,
3,
7,
4,
4,
7
]
},
{
"label": "Selbseinschätzung",
"backgroundColor": "rgb(240,223,89)",
"data": [
7,
4,
4,
3,
6,
5,
2
]
}
]
}
}
}
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, {
type: 'bar',
data: data,
options: chartOptions,
plugins: [circles]
});
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.9.1/dist/chart.min.js"></script>
<html>
<body>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"/>
</div>
</body>
</html>

Select All and Unselect Option for chart.js

I'm Working on Chart.js, wanted to implement Select All and Unselect All option for labels. I'm trying to find it out but couldn't get anything such.
Please do help me out if anything such feature can be implemented.
If you need to show/hide charts selecting/unselecting all labels here is an example:
var barChartData = {
labels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32],
datasets: [{
label: 'One',
backgroundColor: 'rgba(206, 0, 23, 1)',
data: [0, 1, 3, 0, 2, 0, 0, 2, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 2, 1, 0, 1, 2, 1, 1, 0, 0, 0, 2, 2, 0, 3]
}, {
label: 'Two',
backgroundColor: 'rgba(206, 0, 23, 0.75)',
data: [0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1]
}, {
label: 'Three',
backgroundColor: 'rgba(206, 0, 23, 0.5)',
data: [0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 1]
}]
};
var ctx = document.getElementById('canvas').getContext('2d');
var chartInstance = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
title: {
display: false,
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
});
$("#toggle").click(function() {
chartInstance.data.datasets.forEach(function(ds) {
ds.hidden = !ds.hidden;
});
chartInstance.update();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<button id="toggle">show/hide all</button>
<canvas id="canvas" height="500" width="800"></canvas>
Jsfiddle: https://jsfiddle.net/beaver71/00q06vjp/
Credits: see https://github.com/chartjs/Chart.js/issues/3009
Update: for pie chart use "meta", see: https://jsfiddle.net/beaver71/u0y0919b/
For ChartJS 2.9.3, this works as requested by David in the comments:
const chart = ...
chart.data.datasets.forEach(dataset => {
Object.keys(dataset._meta).forEach(key => {
const current = !dataset._meta[key].hidden
dataset._meta[key].hidden = current || null
})
})
chart.update()
Toggles all with a button, while playing nicely with the individual toggling in the chart legend.
V3 Answer
You can use a custom generateLabels function together with a custom onClick to get it as an extra legendItem like so:
const defaultLegendClickHandler = Chart.defaults.plugins.legend.onClick;
const pieDoughnutLegendClickHandler = Chart.controllers.doughnut.overrides.plugins.legend.onClick;
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'orange'
}
]
},
options: {
plugins: {
legend: {
onClick: (evt, legendItem, legend) => {
const type = legend.chart.config.type;
let allLegendItemsState = [];
if (legendItem.text === 'hide all datasets' || legendItem.text === 'show all datasets') {
if (typeof legend.hideAll === 'undefined') {
legend.hideAll = false;
}
legend.chart.data.datasets.forEach((dataset, i) => {
legend.chart.setDatasetVisibility(i, legend.hideAll)
});
legend.hideAll = !legend.hideAll;
legend.chart.update();
return;
}
if (type === 'pie' || type === 'doughnut') {
pieDoughnutLegendClickHandler(evt, legendItem, legend)
} else {
defaultLegendClickHandler(evt, legendItem, legend);
}
allLegendItemsState = legend.chart.data.datasets.map((e, i) => (legend.chart.getDatasetMeta(i).hidden));
if (allLegendItemsState.every(el => !el)) {
legend.hideAll = false;
legend.chart.update();
} else if (allLegendItemsState.every(el => el)) {
legend.hideAll = true;
legend.chart.update();
}
},
labels: {
generateLabels: (chart) => {
const datasets = chart.data.datasets;
const {
labels: {
usePointStyle,
pointStyle,
textAlign,
color
}
} = chart.legend.options;
const legendItems = chart._getSortedDatasetMetas().map((meta) => {
const style = meta.controller.getStyle(usePointStyle ? 0 : undefined);
return {
text: datasets[meta.index].label,
fillStyle: style.backgroundColor,
fontColor: color,
hidden: !meta.visible,
lineCap: style.borderCapStyle,
lineDash: style.borderDash,
lineDashOffset: style.borderDashOffset,
lineJoin: style.borderJoinStyle,
strokeStyle: style.borderColor,
pointStyle: pointStyle || style.pointStyle,
rotation: style.rotation,
textAlign: textAlign || style.textAlign,
datasetIndex: meta.index
};
});
legendItems.push({
text: (!chart.legend.hideAll || typeof chart.legend.hideAll === 'undefined') ? 'hide all datasets' : 'show all datasets',
fontColor: color,
fillStyle: 'turquoise', // Box color
strokeStyle: 'turquoise', // LineCollor around box
});
return legendItems;
}
}
}
}
}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.js"></script>
</body>
The correct answer result in :
chart.data.datasets.forEach((obj, index) => {
let meta = this.eval_chart.getDatasetMeta(index);
meta.hidden = !meta.hidden || null;
});
chart.update();
As wrote in the documentation : https://www.chartjs.org/docs/latest/configuration/legend.html#custom-on-click-actions

How to make a rotating cube move horizontally?

I used C++/OpenGL and drew a rotating cube. Now I want to make it move horizontally while it is rotating. I put a line glTranslatef(0.01, 0, 0). It moves horizontally but does not rotate. Following is my code. Any idea how to fix it so that the cube can move horizontally across while it is rotating?
void drawcube(void) {
int p[][3] = { { 1, 1, 1 }, { 1, -1, 1 }, { -1, -1, 1 }, { -1, 1, 1 },
{ 1, 1, -1 }, { 1, -1, -1 }, { -1, -1, -1 }, { -1, 1, -1 } };
int e[][4] = { { 0, 3, 2, 1 }, { 3, 7, 6, 2 }, { 7, 4, 5, 6 }, { 4, 0, 1, 5 },
{ 0, 4, 7, 3 }, { 1, 2, 6, 5 } };
float c[][3] = { { 1.0, 0, 0 }, { 0, 1.0, 0 }, { 1.0, 1.0, 0.0 },{ 0, 0, 1.0 }, { .6, 0, .6 }, { 0, .6, .6 } };
int i;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef(0.01, 0, 0);
glRotatef(global.angle, 1.0, 1.0, 1.0);
for (i = 0; i < 6; ++i) {
glColor3fv(c[i]);
glBegin(GL_QUADS);
glVertex3iv(p[e[i][0]]);
glVertex3iv(p[e[i][1]]);
glVertex3iv(p[e[i][2]]);
glVertex3iv(p[e[i][3]]);
glEnd();
}
glutSwapBuffers();
}

Retrieving an array from a multi-dimensional array

I'm working on some mathematics research, and I'm having difficulty working my way through the c++ language. Specifically, (and i'm not sure if this is even possible) I'd like to retrieve an array from a multi-dimensional array. Let me clarify. As I understand it, a multi-dimensional array is an array of arrays. I am working with a 3-D array, and what I want to do is retrieve an entire 2-D array from that 3-D array. Here is a snippet from my code. The first declarations are how I had it before (with 15 2-D arrays), the next declaration is how I want things to go (so that I can use a while loop to move through all my 2-D arrays checking for things as it goes).
int round1[3][2] = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
int round2[3][2] = { { 1, 2 }, { 3, 5 }, { 4, 6 } };
int round3[3][2] = { { 1, 2 }, { 3, 6 }, { 4, 5 } };
int round4[3][2] = { { 1, 3 }, { 2, 4 }, { 5, 6 } };
int round5[3][2] = { { 1, 3 }, { 2, 5 }, { 4, 6 } };
int round6[3][2] = { { 1, 3 }, { 2, 6 }, { 4, 5 } };
int round7[3][2] = { { 1, 4 }, { 2, 3 }, { 5, 6 } };
int round8[3][2] = { { 1, 4 }, { 2, 5 }, { 3, 6 } };
int round9[3][2] = { { 1, 4 }, { 2, 6 }, { 3, 5 } };
int round10[3][2] = { { 1, 5 }, { 2, 3 }, { 4, 6 } };
int round11[3][2] = { { 1, 5 }, { 2, 4 }, { 3, 6 } };
int round12[3][2] = { { 1, 5 }, { 2, 6 }, { 3, 4 } };
int round13[3][2] = { { 1, 6 }, { 2, 3 }, { 4, 5 } };
int round14[3][2] = { { 1, 6 }, { 2, 4 }, { 3, 5 } };
int round15[3][2] = { { 1, 6 }, { 2, 5 }, { 3, 4 } };
int rounds[15][3][2] = { { { 1, 2 }, { 3, 4 }, { 5, 6 } }, { { 1, 2 }, { 3, 5 }, { 4, 6 } }, { { 1, 2 }, { 3, 6 }, { 4, 5 } }, { { 1, 3 }, { 2, 4 }, { 5, 6 } }, { { 1, 3 }, { 2, 5 }, { 4, 6 } }, { { 1, 3 }, { 2, 6 }, { 4, 5 } }, { { 1, 4 }, { 2, 3 }, { 5, 6 } }, { { 1, 4 }, { 2, 5 }, { 3, 6 } }, { { 1, 4 }, { 2, 6 }, { 3, 5 } }, { { 1, 5 }, { 2, 3 }, { 4, 6 } }, { { 1, 5 }, { 2, 4 }, { 3, 6 } }, { { 1, 5 }, { 2, 6 }, { 3, 4 } }, { { 1, 6 }, { 2, 3 }, { 4, 5 } }, { { 1, 6 }, { 2, 4 }, { 3, 5 } }, { { 1, 6 }, { 2, 5 }, { 3, 4 } } };
int tourney_count = 0;
string tourney[5] = { "", "", "", "", "" };
int roundcount_a = 0;
int roundcount_b = 0;
int roundcount_c = 0;
int roundcount_d = 0;
int roundcount_e = 0;
if (is_compatible(rounds[0][][], rounds[3][][]))
//do stuff
return 0;
is_compatible is a function I've defined above that basically checks to see if any two 2-D arrays contain like pairs. My plan is to do some work with while loops (haven't quite figured it all out yet) to go through my 3-D array and move from one to the next checking to see which ones are compatible, and then moving on to a third array. That's about it.
If anyone has any better ideas on how to go about something like this (not using arrays in arrays in arrays), then I would be happy to hear you out. However, I'd really just like to know if I can do what i'm trying to do and return one of these 2-D arrays from a 3-D array.
Thanks.

Problems initializing arrays in structs in arrays in structs

I've been tasked to remove some compiler warning. I've been able to boil the problem down to the following example, which I am scratching my head why it won't work. I guess I don't know how to initialize stuff in C++. Any help would be appreciated.
I use g++ like so:
g++ init_arr.cpp
Here's the code. I want to initialize all the people at all the tables in Aisle pizza:
// init_arr.cpp
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct Person {
int id;
string name;
double money;
};
struct Table {
Person tab[4];
};
struct Aisle {
Table ais[3];
};
int main() {
cout << "main function()" << endl;
Aisle pizza =
{
{ // Table 0
{ 0, "Tom", 100.0 },
{ 1, "Mary", 101.0 },
{ 2, "Jane", 103.0 },
{ 3, "Joe", 104.0 }
},
{ // Table 1
{ 0, "Tom", 100.0 },
{ 1, "Mary", 101.0 },
{ 2, "Jane", 103.0 },
{ 3, "Joe", 104.0 }
},
{ // Table 2
{ 0, "Tom", 100.0 },
{ 1, "Mary", 101.0 },
{ 2, "Jane", 103.0 },
{ 3, "Joe", 104.0 }
}
};
return 0;
}
I thought the above would work, but I get the following error:
g++ init_arr.cpp -std=gnu++0x
init_arr.cpp: In function ‘int main()’:
init_arr.cpp:49: error: too many initializers for ‘Table [3]’
init_arr.cpp:49: error: too many initializers for ‘Aisle’
While #us2012 showed what works and provides a good explanation (+1 for him), I find it not very readable. This is an alternative:
Aisle pizza =
{
Table { // Table 0
Person { 0, "Tom", 100.0 },
Person { 1, "Mary", 101.0 },
Person { 2, "Jane", 103.0 },
Person { 3, "Joe", 104.0 }
},
Table { // Table 1
Person { 0, "Tom", 100.0 },
Person { 1, "Mary", 101.0 },
Person { 2, "Jane", 103.0 },
Person { 3, "Joe", 104.0 }
},
Table { // Table 2
Person { 0, "Tom", 100.0 },
Person { 1, "Mary", 101.0 },
Person { 2, "Jane", 103.0 },
Person { 3, "Joe", 104.0 }
}
};
You're missing lots of pairs of parentheses. I have added comments to make it clearer which bit starts where.
To put it into one sentence, your problem is that an array with three elements can be initialized with {1,2,3} while a struct that contains an array as its single member is an extra layer and therefore has to be initalized with { {1,2,3} } - the outer layer is the struct, the inner layer is the array.
Aisle pizza =
{ // Aisle init
{ // Table ais[3] init
{ // ais[0] init
{ // Person tab[4] init
{ 0, "Tom", 100.0 },
{ 1, "Mary", 101.0 },
{ 2, "Jane", 103.0 },
{ 3, "Joe", 104.0 }
}
},
{ // ais[1] init
{ // Person tab[4] init
{ 0, "Tom", 100.0 },
{ 1, "Mary", 101.0 },
{ 2, "Jane", 103.0 },
{ 3, "Joe", 104.0 }
}
},
{ // ais[2] init
{ // Person tab[4] init
{ 0, "Tom", 100.0 },
{ 1, "Mary", 101.0 },
{ 2, "Jane", 103.0 },
{ 3, "Joe", 104.0 }
}
}
}
};
Each block needs to represent an object. Aisle struct contains an array object (ais). Each element of the ais array contains a Table struct. Each Table struct contains an array object (tab). and so on...
Try this:
Aisle pizza =
{ // Aisle
{ // .ais
{ // .ais[0]
{ // .ais[0].tab
{ 0, "Tom", 100.0 }, // tab[0]
{ 1, "Mary", 101.0 }, // tab[1]
{ 2, "Jane", 103.0 }, // tab[2]
{ 3, "Joe", 104.0 } // tab[3]
}
},
{ // .ais[1]
{ // .ais[1].tab
{ 0, "Tom", 100.0 }, // tab[0]
{ 1, "Mary", 101.0 }, // tab[1]
{ 2, "Jane", 103.0 }, // tab[2]
{ 3, "Joe", 104.0 } // tab[3]
}
},
{ // .ais[2]
{ // .ais[2].tab
{ 0, "Tom", 100.0 }, // tab[0]
{ 1, "Mary", 101.0 }, // tab[1]
{ 2, "Jane", 103.0 }, // tab[2]
{ 3, "Joe", 104.0 } // tab[3]
}
}
}
};