Enschede - The Netherlands
Offline
Jr. Member
Karma: 0
Posts: 66
|
 |
« on: September 19, 2011, 11:23:28 am » |
I'm trying to make a pointer to a multidimensional array. Any idea how to do that? In my old post I already found out how to do that with one array. http://arduino.cc/forum/index.php/topic,53807.0.htmlMy code. int _rybWheel[25][3] = { { 0 , 255, 255 }, // 0 { 12 , 255, 255 }, // 15 { 24 , 255, 255 }, // 30 { 30 , 255, 255 }, // 45 { 36 , 255, 255 }, // 60 { 42 , 255, 255 }, // 75 { 48 , 255, 255 }, // 90 { 54 , 255, 255 }, // 105 { 60 , 255, 255 }, // 120 { 72 , 255, 255 }, // 135 { 84 , 255, 255 }, // 150 { 108, 255, 255 }, // 165 { 120, 255, 255 }, // 180 { 154, 255, 255 }, // 195 { 180, 255, 255 }, // 210 { 206, 255, 255 }, // 225 { 225, 255, 255 }, // 240 { 240, 255, 255 }, // 255 { 260, 255, 255 }, // 270 { 265, 255, 255 }, // 285 { 280, 255, 255 }, // 300 { 300, 255, 255 }, // 315 { 315, 255, 255 }, // 330 { 333, 255, 255 }, // 345 { 360, 255, 255 } // 360 };
I declare the array in the .h file like this: int* rybWheel;
And in the constructor I write. rybWheel = _rybWheel;
And I do this in a function (thats the error on line 360) Serial.println(rybWheel[rybWheelIndex+1][0],DEC); I get these errors: /Users/macbook/Dropbox/code/_arduino/libraries/ColorLight/ColorLight.cpp: In constructor 'ColourPalette::ColourPalette()': /Users/macbook/Dropbox/code/_arduino/libraries/ColorLight/ColorLight.cpp:55: error: cannot convert 'int [25][3]' to 'int*' in assignment /Users/macbook/Dropbox/code/_arduino/libraries/ColorLight/ColorLight.cpp: In member function 'void ColourPalette::ColourAtRYBWheel(int, int*)': /Users/macbook/Dropbox/code/_arduino/libraries/ColorLight/ColorLight.cpp:360: error: invalid types 'int[int]' for array subscript
I've looked up some information on pointers, but I cannot find clear information about pointers to multidimensional arrays and how I can use that with Arduino.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Online
Brattain Member
Karma: 316
Posts: 35566
Seattle, WA USA
|
 |
« Reply #1 on: September 19, 2011, 11:31:28 am » |
A two dimensional array is really an array of pointers to one dimensional arrays. So, a pointer to a 2D array needs two stars. int** rybWheel;
|
|
|
|
|
Logged
|
|
|
|
|
Enschede - The Netherlands
Offline
Jr. Member
Karma: 0
Posts: 66
|
 |
« Reply #2 on: September 19, 2011, 12:37:01 pm » |
Yes, but if I try that then I get this error: /Users/macbook/Dropbox/code/_arduino/libraries/ColorLight/ColorLight.cpp:55: error: cannot convert 'int [25][3]' to 'int**' in assignment
I tried this as well: rybWheel = &_rybWheel;
error: /Users/macbook/Dropbox/code/_arduino/libraries/ColorLight/ColorLight.cpp:55: error: cannot convert 'int (*)[25][3]' to 'int**' in assignment
Pointer is still a hard subject to grab for me.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Online
Brattain Member
Karma: 316
Posts: 35566
Seattle, WA USA
|
 |
« Reply #3 on: September 19, 2011, 12:43:59 pm » |
Yes, but if I try that then I get this error: Lean a little to the left. I can't see line 55. A little further... No, still can't see. Ooh, careful, don't fall off the chair.
|
|
|
|
|
Logged
|
|
|
|
|
Enschede - The Netherlands
Offline
Jr. Member
Karma: 0
Posts: 66
|
 |
« Reply #4 on: September 19, 2011, 02:01:36 pm » |
Ok, sorry for not clearly documenting it. I've made a minimized version of the code, that gives me the error. The Colorlight.h file #ifndef ColorLight_h #define ColorLight_h
#include "WProgram.h"
class ColourPalette { public: ColourPalette(); int** rybWheel; }; #endif
The ColorLight.cpp file #include "WProgram.h" #include "ColorLight.h"
int _rybWheel[25][3] = { { 0 , 255, 255 }, // 0 { 12 , 255, 255 }, // 15 { 24 , 255, 255 }, // 30 { 30 , 255, 255 }, // 45 { 36 , 255, 255 }, // 60 { 42 , 255, 255 }, // 75 { 48 , 255, 255 }, // 90 { 54 , 255, 255 }, // 105 { 60 , 255, 255 }, // 120 { 72 , 255, 255 }, // 135 { 84 , 255, 255 }, // 150 { 108, 255, 255 }, // 165 { 120, 255, 255 }, // 180 { 154, 255, 255 }, // 195 { 180, 255, 255 }, // 210 { 206, 255, 255 }, // 225 { 225, 255, 255 }, // 240 { 240, 255, 255 }, // 255 { 260, 255, 255 }, // 270 { 265, 255, 255 }, // 285 { 280, 255, 255 }, // 300 { 300, 255, 255 }, // 315 { 315, 255, 255 }, // 330 { 333, 255, 255 }, // 345 { 360, 255, 255 } // 360 };
ColourPalette::ColourPalette() { rybWheel = _rybWheel; }
This will give the error below: /Users/macbook/Dropbox/code/_arduino/libraries/ColorLight/ColorLight.cpp: In constructor 'ColourPalette::ColourPalette()': /Users/macbook/Dropbox/code/_arduino/libraries/ColorLight/ColorLight.cpp:37: error: cannot convert 'int [25][3]' to 'int**' in assignment
Line 37 is rybWheel = _rybWheel;
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
UK
Offline
Brattain Member
Karma: 138
Posts: 19067
I don't think you connected the grounds, Dave.
|
 |
« Reply #5 on: September 19, 2011, 02:04:56 pm » |
A two dimensional array is really an array of pointers to one dimensional arrays No, that would be an Iliffe vector. A two dimensional array is really just a concatentation of one dimensional arrays.
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
Seattle, WA USA
Online
Brattain Member
Karma: 316
Posts: 35566
Seattle, WA USA
|
 |
« Reply #6 on: September 19, 2011, 02:18:09 pm » |
In the ColorLight.cpp file, you are defining a global variable, _rybWheel. I guess that I am at a loss to understand why you need a member variable that points to it, but, this compiles: ColourPalette::ColourPalette() { rybWheel = (int **)_rybWheel; }
|
|
|
|
|
Logged
|
|
|
|
|
Enschede - The Netherlands
Offline
Jr. Member
Karma: 0
Posts: 66
|
 |
« Reply #7 on: September 20, 2011, 01:52:33 am » |
Well, I think I don't really get what I'm doing. Declaring things in the .h file is new for me for example.
The problem was that I got back a lot of number that we're not in the array. So for sure the array didn't exist anymore and I got back some other data from the same memory address.
I now declared the array as a normal global array and not as a member variable (I suppose a member variable is a variable of an object). Is it right that I don't have to put those global variables in the header (.h) file? It works for now at least.
I'm trying to port some classes I wrote in Processing to Arduino, but that seems more difficult then I expected.
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
UK
Offline
Brattain Member
Karma: 138
Posts: 19067
I don't think you connected the grounds, Dave.
|
 |
« Reply #8 on: September 20, 2011, 03:09:24 am » |
int _rybWheel[25][3] = Serial.println(rybWheel[rybWheelIndex+1][0],DEC); The problem is that the declaration tells the compiler that your array consists of twenty-five rows of three "int"s. The rows are arranged in memory one after the other, so _rbyWheel[1][0] has an address six bytes (two bytes per "int") higher than _rbyWheel[0][0] If you simply assign a pointer to the start of the array int* rybWheel = _rybWheel; , then the compiler has lost the ability to know what the length of each row is - the pointer could point to an array of three rows of twenty-five elements, or a simple vector of seventy-five elements. However, the compiler doesn't need to know the number of rows, just their length. int (*rybWheel)[3] = _rybWheel;
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
Enschede - The Netherlands
Offline
Jr. Member
Karma: 0
Posts: 66
|
 |
« Reply #9 on: September 20, 2011, 05:43:33 am » |
I'm still struggling with strange values. However I don't know how to solve it. I thought its was related to the pointer and the array, but I'm not sure now. I've updated my code and now use a normal global array (for this example I removed the multidimensional array that I used above). My code: header file: #ifndef ColorLight_h #define ColorLight_h
#include "WProgram.h"
class ColourBase { public: ColourBase(); int baseHue; // hue value on the circle float *wheelHSBColor; };
class ColourPalette { public: ColourPalette(); int mainHue; int complementOffset; int hueAngle; int complementAngle; ColourBase cArray[6]; void updatePalette(); void ColourAtRYBWheel(int, float*); float lerp(float, float, float); }; #endif
.cpp file #include "WProgram.h" #include "ColorLight.h"
const int rybHueWheel[25] = { 0 , 12 , 24 , 30 , 36 , 42 , 48 , 54 , 60 , 72 , 84 , 108, 120, 154, 180, 206, 225, 240, 260, 265, 280, 300, 315, 333, 360 };
ColourBase::ColourBase() { float wheelHSBColor[3]; }
ColourPalette::ColourPalette() { mainHue = 5; complementOffset = 0; hueAngle = 30; complementAngle = 30; updatePalette(); }
void ColourPalette::updatePalette() { Serial.println("update palette"); cArray[0].baseHue = mainHue; cArray[1].baseHue = mainHue - hueAngle; cArray[2].baseHue = mainHue + hueAngle; cArray[3].baseHue = mainHue + 180 + complementOffset; cArray[4].baseHue = cArray[3].baseHue - complementAngle; cArray[5].baseHue = cArray[3].baseHue + complementAngle;
// convert to new hue numbers with the new ColorWheel (HueToRYB) for (int i=0; i<6;i++) { ColourAtRYBWheel(cArray[i].baseHue, cArray[i].wheelHSBColor); } }
void ColourPalette::ColourAtRYBWheel(int hue, float c[3]) { if (hue<0) hue = 360+hue; hue = hue%360; // stick to 0 - 359
int rybWheelIndex = hue/15; // colourWheel has 24 base colours float rybWheelAmount = (hue%15)/15.0; // interpolate amount
c[0] = lerp(rybHueWheel[rybWheelIndex], rybHueWheel[rybWheelIndex+1], rybWheelAmount); c[1] = lerp(rybHueWheel[4], rybHueWheel[5], rybWheelAmount); c[2] = lerp(255, 255, rybWheelAmount); Serial.print("hue : "); Serial.println(hue, DEC); Serial.print("wheelindex: "); Serial.println(rybWheelIndex, DEC); Serial.print("wheelamount: "); Serial.println(rybWheelAmount,DEC); Serial.println("==================="); }
float ColourPalette::lerp(float a, float b, float x) { return(a*(1-x) + b*x); }
If I print this I'll get: update palette hue : -32704 wheelindex: 0 wheelamount: -30704688.0000000000 =================== hue : -24509 wheelindex: 0 wheelamount: -30704688.0000000000 =================== hue : -12223 wheelindex: 0 wheelamount: -30704688.0000000000 =================== hue : 835 wheelindex: 0 wheelamount: -30704688.0000000000 =================== hue : -18366 wheelindex: 0 wheelamount: -30704688.0000000000 =================== hue : 15427 wheelindex: 0 wheelamount: -30704688.0000000000 ===================
However when I comment the lines that start with c[1] and [c2] I get the right output. c[0] = lerp(rybHueWheel[rybWheelIndex], rybHueWheel[rybWheelIndex+1], rybWheelAmount); //c[1] = lerp(rybHueWheel[4], rybHueWheel[5], rybWheelAmount); //c[2] = lerp(255, 255, rybWheelAmount);
update palette hue : 5 wheelindex: 0 wheelamount: 0.3333333492 =================== hue : 335 wheelindex: 22 wheelamount: 0.3333333492 =================== hue : 35 wheelindex: 2 wheelamount: 0.3333333492 =================== hue : 185 wheelindex: 12 wheelamount: 0.3333333492 =================== hue : 155 wheelindex: 10 wheelamount: 0.3333333492 =================== hue : 215 wheelindex: 14 wheelamount: 0.3333333492 ===================
So repeatedly calling the lerp function gives this bug. Has it the do with a lack of memory? I don't know if its smart to use floats (since I read about speed issues), but I cannot find good examples of fixed point or integer linair interpolation functions. Also the question if its possible to use the Flash library like this ( http://arduiniana.org/libraries/flash/) in my library. Is it just including the .h and files? Are there any examples on that?
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Online
Brattain Member
Karma: 316
Posts: 35566
Seattle, WA USA
|
 |
« Reply #10 on: September 20, 2011, 09:05:24 am » |
ColourBase::ColourBase() { float wheelHSBColor[3]; } What do you think this is doing? You've declared a local variable that immediately goes out of scope. You are not assigning any values to it. class ColourBase { public: ColourBase(); int baseHue; // hue value on the circle float *wheelHSBColor; }; The variable ColourBase::wheelHSBColor is a pointer that points nowhere. This is likely NOT what you want, since the constructor doesn't point it anywhere, either. ColourAtRYBWheel(cArray[i].baseHue, cArray[i].wheelHSBColor); You are calling this function with a pointer (cArray .wheelHSBColor) that points nowhere.
void ColourPalette::ColourAtRYBWheel(int hue, float c[3]) { // Snipped some code
c[0] = lerp(rybHueWheel[rybWheelIndex], rybHueWheel[rybWheelIndex+1], rybWheelAmount); c[1] = lerp(rybHueWheel[4], rybHueWheel[5], rybWheelAmount); c[2] = lerp(255, 255, rybWheelAmount); And, even though c is not a real array (you have allocated no space for it), you try to write to that space. As you have figured out, you can't do that (successfully).
|
|
|
|
|
Logged
|
|
|
|
|
Enschede - The Netherlands
Offline
Jr. Member
Karma: 0
Posts: 66
|
 |
« Reply #11 on: September 20, 2011, 09:25:19 am » |
Paul thanks for the great help you provide here in the forum helping to solve some problems. I think I've solved part of the problem. Stupid indeed not to assign values to the arrays and the ColourBase object. Although I have the idea that I did everything good now, there still goes something wrong with the c array in combination with the ColourAtRYBWheel function. My .h file #ifndef ColorLight_h #define ColorLight_h
#include "WProgram.h"
class ColourBase { public: ColourBase(); int baseHue; // hue value on the circle int *wheelHSBColor; };
class ColourPalette { public: ColourPalette(); int mainHue; int complementOffset; int hueAngle; int complementAngle; ColourBase *cArray; void updatePalette(); void ColourAtRYBWheel(int, int*); int lerpInt(int, int, int, int); }; #endif
My .cpp file ##include "WProgram.h" #include "ColorLight.h"
const int rybHueWheel[25] = { 0 , 12 , 24 , 30 , 36 , 42 , 48 , 54 , 60 , 72 , 84 , 108, 120, 154, 180, 206, 225, 240, 260, 265, 280, 300, 315, 333, 360 };
ColourBase::ColourBase() { int wheelHSBColor[] = {0, 0, 0}; }
ColourPalette::ColourPalette() { ColourBase cArray[6]; for (int i=0;i<6; i++) { cArray[i] = ColourBase(); } mainHue = 5; complementOffset = 0; hueAngle = 30; complementAngle = 30; updatePalette(); }
void ColourPalette::updatePalette() { Serial.println("update palette"); cArray[0].baseHue = mainHue; cArray[1].baseHue = mainHue - hueAngle; cArray[2].baseHue = mainHue + hueAngle; cArray[3].baseHue = mainHue + 180 + complementOffset; cArray[4].baseHue = cArray[3].baseHue - complementAngle; cArray[5].baseHue = cArray[3].baseHue + complementAngle;
// convert to new hue numbers with the new ColorWheel (HueToRYB) for (int i=0; i<6;i++) { ColourAtRYBWheel(cArray[i].baseHue, cArray[i].wheelHSBColor); } }
void ColourPalette::ColourAtRYBWheel(int hue, int c[3]) { if (hue<0) hue = 360+hue; hue = hue%360; // stick to 0 - 359
int rybWheelIndex = hue/15; // colourWheel has 24 base colours int rybWheelAmount = hue%15; c[0] = lerpInt(rybHueWheel[rybWheelIndex], rybHueWheel[rybWheelIndex+1], rybWheelAmount,15); Serial.print("hue : "); Serial.println(hue, DEC); Serial.print("wheelindex: "); Serial.println(rybWheelIndex, DEC); Serial.print("val in wheelindex: "); Serial.println(rybHueWheel[rybWheelIndex], DEC); Serial.print("val in wheelindex +1 : "); Serial.println(rybHueWheel[rybWheelIndex+1], DEC); Serial.print("wheelamount: "); Serial.println(rybWheelAmount,DEC); Serial.print("result in array: "); Serial.println(c[0],DEC); Serial.print("result direct: "); Serial.println(lerpInt(rybHueWheel[rybWheelIndex], rybHueWheel[rybWheelIndex+1], rybWheelAmount,15));
Serial.println("==================="); }
int ColourPalette::lerpInt(int a, int b, int f, int max) { // f is a number between 0 - max return a + ( (b-a) * f/max ); }
I think something goes wrong with writing values to the c array in the function ColourAtRYBWheel. Probably its still not declared ok, but how can I solve that. The results I print. In all cases the "result in array" should be the same as "result direct". I two cases thats not the case, so the number changes somewhere in between. update palette hue : 5 wheelindex: 0 val in wheelindex: 0 val in wheelindex +1 : 12 wheelamount: 5 result in array: 198 result direct: 4 =================== hue : 335 wheelindex: 22 val in wheelindex: 315 val in wheelindex +1 : 333 wheelamount: 5 result in array: 321 result direct: 321 =================== hue : 35 wheelindex: 2 val in wheelindex: 24 val in wheelindex +1 : 30 wheelamount: 5 result in array: 0 result direct: 26 =================== hue : 185 wheelindex: 12 val in wheelindex: 120 val in wheelindex +1 : 154 wheelamount: 5 result in array: 131 result direct: 131 =================== hue : 16 wheelindex: 1 val in wheelindex: 12 val in wheelindex +1 : 0 wheelamount: 1 result in array: 12 result direct: 12 =================== hue : 10 wheelindex: 0 val in wheelindex: 0 val in wheelindex +1 : 12 wheelamount: 10 result in array: 8 result direct: 8 ===================
I've implemented a lerp with only integers, so that part of the problem is solved.
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
UK
Offline
Brattain Member
Karma: 138
Posts: 19067
I don't think you connected the grounds, Dave.
|
 |
« Reply #12 on: September 20, 2011, 09:27:19 am » |
ColourPalette::ColourPalette() { ColourBase cArray[6]; // GET RID OF THIS! for (int i=0;i<6; i++) { cArray[i] = ColourBase(); } mainHue = 5; complementOffset = 0; hueAngle = 30; complementAngle = 30; updatePalette(); }
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
Seattle, WA USA
Online
Brattain Member
Karma: 316
Posts: 35566
Seattle, WA USA
|
 |
« Reply #13 on: September 20, 2011, 09:31:48 am » |
int *wheelHSBColor; Changing the type from float to int doesn't change the fact that this points nowhere. ColourBase::ColourBase() { int wheelHSBColor[] = {0, 0, 0}; } Changing the type from float to int doesn't change the fact that this is a local variable that goes out of scope as soon as the constructor ends. The pointer still points nowhere. c[0] = lerpInt(rybHueWheel[rybWheelIndex], rybHueWheel[rybWheelIndex+1], rybWheelAmount,15);
The c pointer still points to no reserved space, so you still can't write there.
|
|
|
|
|
Logged
|
|
|
|
|
Enschede - The Netherlands
Offline
Jr. Member
Karma: 0
Posts: 66
|
 |
« Reply #14 on: September 20, 2011, 10:20:00 am » |
I'm puzzled. Its clear for me that changing the type doesn't change anything. I don't get that I'm pointing to nowhere. Let me explain how I think and what I want. I've made a ColourBase object to store different variables and arrays. I this case I have only the wheelHSBColor array and the baseHue integer, but I'd like to use more arrays and variables. So I make 6 ColourBase objects in the constructor of the ColourPalette ColourBase cArray[6]; // calling this I allocated the space for an array with 6 ColourBase objects? for (int i=0;i<6; i++) { cArray[i] = ColourBase(); // here I will "fill up" the array with new created ColourBase objects. }
By calling ColourBase(); I assume that I create 6 ColourBase() objects and also allocate memory space for the wheelHSBColor[] array since I create an array by doing this in the ColourBase constructor: int wheelHSBColor[] = {0, 0, 0};
In the updatePalette() function called from the ColourPalette constructor I will set the value of each baseHue variable in each ColourBase object cArray[0].baseHue = mainHue; cArray[1].baseHue = mainHue - hueAngle; cArray[2].baseHue = mainHue + hueAngle; cArray[3].baseHue = mainHue + 180 + complementOffset; cArray[4].baseHue = cArray[3].baseHue - complementAngle; cArray[5].baseHue = cArray[3].baseHue + complementAngle;
Then I'll call the ColourAtRYBWheel function to fill the wheelHSBColor array in each ColourBase object (stored in the cArray) for (int i=0; i<6;i++) { ColourAtRYBWheel(cArray[i].baseHue, cArray[i].wheelHSBColor); }
In my assumption does c[0] point to index[0] of the wheelHSBColor array as index c[1] will point to wheelHSBColor[1]. Since I use a for-loop I think I'll fill each wheelHSBColor array for each ColorBase object. I hope I cleared up my way of thinking. Hope you can point out what goes wrong. Thank you in advance.
|
|
|
|
|
Logged
|
|
|
|
|
|