Pages: 1 [2]   Go Down
Author Topic: a pointer to a multidimensional array  (Read 1704 times)
0 Members and 1 Guest are viewing this topic.
Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 638
Posts: 50304
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I don't get that I'm pointing to nowhere.
A pointer is like a card with an address on it. When you dereference the pointer, you look at the address on the card to find where the data is/goes.

Your pointers are like blank cards. When you want to store data at the address on the card, and there is no address on the card, what do you do?

Write there anyway is not the right answer.

You need to make the pointer point to some space where you have permission to write to. That can be a static array, or to a dynamically allocated block of memory. Either way, you get an address on your card, so you CAN store data there.

Pointers are powerful, but they are not magic. Something (that's code you write) needs to make the pointer point somewhere.

Quote
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:
You are defining an array, but that array is local in scope (limited to the constructor) and lifetime (it goes away when the constructor ends).
Logged

Enschede - The Netherlands
Offline Offline
Jr. Member
**
Karma: 0
Posts: 75
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, using pointers is still hard to grasp for me, thank your for the clear metaphor.

Quote
You are defining an array, but that array is local in scope (limited to the constructor) and lifetime (it goes away when the constructor ends).

So I have to do this in the .h file in the public section of the class?
Code:
int wheelHSBColor[3];

And for the cArray:
Code:
ColourBase cArray[6];

I thought I couldn't initialize anything in the .h files, but I think I was wrong?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 638
Posts: 50304
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I thought I couldn't initialize anything in the .h files, but I think I was wrong?
You can't initialize things in the header file. Initialization is done in the source file.

Yes, those changes are needed and proper.
Logged

Enschede - The Netherlands
Offline Offline
Jr. Member
**
Karma: 0
Posts: 75
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Completely clear now. Thanks for the effort explaining it.
Logged

Enschede - The Netherlands
Offline Offline
Jr. Member
**
Karma: 0
Posts: 75
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

And back again with another question. .. smiley-sad

I think I have a problem with the Colourbase objects. Because I get back some messed up values again. 

I initialize my ColourBase objects like this:
Code:
for (int i=0;i<6; i++)
{ cArray[i] = ColourBase();
}
Is that good or is the memory space then not allocated? I've read that the "new" is not supported. I looked in this forum post:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1216134904
and try to include the code, but I get a multiple definition error (so I suppose its already somewhere, but where?).

I try to refer to the ColourBase objects in a function like this:
Code:
calculateShadeTint(cArray[i]);  // call to function and passing the object

void ColourPalette::calculateShadeTint(ColourBase c)
{
  c.tintHSBColor[0] = c.wheelHSBColor[0];
  c.tintHSBColor[1] = 255;
  c.tintHSBColor[2] = 255;
}

What do I do wrong?




Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 638
Posts: 50304
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is that good or is the memory space then not allocated?
Add a Serial.print() to the constructor. See if it gets called. If so (and it should), it's good.

Quote
and try to include the code, but I get a multiple definition error (so I suppose its already somewhere, but where?).
How did you implement it? Where did you implement it? Multiple definition of what? No, it's not.

Quote
What do I do wrong?
Hard to say. What does the ColourBase() constructor do? What does the ColourBase class now look like?

Quote
Because I get back some messed up values again. 
And as proof, you offer?
Logged

Enschede - The Netherlands
Offline Offline
Jr. Member
**
Karma: 0
Posts: 75
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry, I needed to make a smaller version of my project to show the problem in the forum, because otherwise the code gets to lengthy.
Below I did.

My .h file:
Code:
#include "WProgram.h"

#ifndef ColorLight_h
#define ColorLight_h

class ColourBase
{
  public:
    ColourBase(); 
   
    float interpolation;
   
  int baseHue;           // hue value on the circle 
int wheelHSBColor[3];
int tintHSBColor[3];
int shadeHSBColor[3];
int interpolatedHSBColor[3]; // interpolated color between shade/tint

unsigned long wheelRGBColor;   
    unsigned long shadeRGBColor;
    unsigned long tintRGBColor;   
    unsigned long interpolatedRGBColor;
};

class ColourPalette
{
  public:
    ColourPalette();
   
protected:
 
int mainHue;
int complementOffset;
int hueAngle;
int complementAngle;

int minSaturation;
int maxSaturation;
int minBrightness;
int maxBrightness;

ColourBase cArray[6];

void setMinSaturation(int);
void setMaxSaturation(int);
void setMinBrightness(int);
void setMaxBrightness(int);

void updatePalette();

void setShadeValues(float, float, float , float);
void calculateShadeTint(ColourBase);

void updateInterpolation(ColourBase);

void ColourAtRYBWheel(int, int*);

int   lerpInt(int, int, int, int);
int   lerpf(int, int, float);

};

#endif

My .cpp file
Code:
#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()
{ interpolation = 0.5;
baseHue = 0;
Serial.println("constructor colourbase");
}

ColourPalette::ColourPalette()
{
//for (int i=0;i<6; i++)
    //{ //cArray[i] = ColourBase();
    //}

// defaults
mainHue = 5;
complementOffset = 0;
hueAngle = 30;
complementAngle = 30;   

minSaturation = 0;
maxSaturation = 255;
minBrightness = 0;
maxBrightness = 255;

updatePalette();
}

// =FUNCTIONS====================================================

void ColourPalette::updatePalette()
{
  Serial.println("- function 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;
 
  for (int i=0; i<6;i++)
  { // convert to new hue numbers with the new ColorWheel (HueToRYB)
  ColourAtRYBWheel(cArray[i].baseHue, cArray[i].wheelHSBColor);
    calculateShadeTint(cArray[i]); 
    updateInterpolation(cArray[i]); 
  } 
}

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);
c[1] = 255; // saturation
c[2] = 255; // brightness

Serial.println();
Serial.print("- function ColourAtRYBWheel result: ");
Serial.print(c[0],DEC);
Serial.print(","); 
Serial.print(c[1],DEC); 
Serial.print(","); 
Serial.println(c[2],DEC); 
}

void ColourPalette::calculateShadeTint(ColourBase c)
{   Serial.println("- function calculateShadeTint");

c.tintHSBColor[0] = c.shadeHSBColor[0] = c.wheelHSBColor[0];
c.shadeHSBColor[1] = minSaturation;
c.tintHSBColor[1]  = maxSaturation; 
c.shadeHSBColor[2] = minBrightness;
c.tintHSBColor[2]  = maxBrightness; 

Serial.print("  c.tintHSBColor[0]: ");
Serial.print(c.tintHSBColor[0]);
Serial.print(" c.shadeHSBColor[0]: ");
Serial.println(c.shadeHSBColor[0]);

Serial.print("  c.tintHSBColor[1]: ");
Serial.print(c.tintHSBColor[1]);
Serial.print(" c.shadeHSBColor[1]: ");
Serial.println(c.shadeHSBColor[1]);
   
Serial.print("  c.tintHSBColor[2]: ");
Serial.print(c.tintHSBColor[2]);
Serial.print(" c.shadeHSBColor[2]: ");
Serial.println(c.shadeHSBColor[2]);   
}

void ColourPalette::updateInterpolation(ColourBase c)
{
Serial.println("- function updateInterpolation");

Serial.print("  c.tintHSBColor[0]: ");
Serial.print(c.tintHSBColor[0]);
Serial.print(" c.shadeHSBColor[0]: ");
Serial.println(c.shadeHSBColor[0]);

Serial.print("  c.tintHSBColor[1]: ");
Serial.print(c.tintHSBColor[1]);
Serial.print(" c.shadeHSBColor[1]: ");
Serial.println(c.shadeHSBColor[1]);

Serial.print("  c.tintHSBColor[2]: ");
Serial.print(c.tintHSBColor[2]);
Serial.print(" c.shadeHSBColor[2]: ");
Serial.println(c.shadeHSBColor[2]); 
}

int ColourPalette::lerpInt(int a, int b, int f, int max)
{ // f is a number between 0 - max
return a + ( (b-a) * f/max );
}

In the function calculateShadeTint I expect to read the same values as in updateInterpolation.
Below you'll see that that doesn't happen.

What is printed:
Code:
constructor colourbase
constructor colourbase
constructor colourbase
constructor colourbase
constructor colourbase
constructor colourbase
- function update palette

- function ColourAtRYBWheel result: 4,255,255
- function calculateShadeTint
  c.tintHSBColor[0]: 4 c.shadeHSBColor[0]: 4
  c.tintHSBColor[1]: 255 c.shadeHSBColor[1]: 0
  c.tintHSBColor[2]: 255 c.shadeHSBColor[2]: 0
- function updateInterpolation
  c.tintHSBColor[0]: -19659 c.shadeHSBColor[0]: -257
  c.tintHSBColor[1]: -4910 c.shadeHSBColor[1]: -1265
  c.tintHSBColor[2]: 16309 c.shadeHSBColor[2]: -722

- function ColourAtRYBWheel result: 321,255,255
- function calculateShadeTint
  c.tintHSBColor[0]: 321 c.shadeHSBColor[0]: 321
  c.tintHSBColor[1]: 255 c.shadeHSBColor[1]: 0
  c.tintHSBColor[2]: 255 c.shadeHSBColor[2]: 0
- function updateInterpolation
  c.tintHSBColor[0]: -19659 c.shadeHSBColor[0]: -257
  c.tintHSBColor[1]: -4910 c.shadeHSBColor[1]: -1265
  c.tintHSBColor[2]: 16309 c.shadeHSBColor[2]: -722

- function ColourAtRYBWheel result: 26,255,255
- function calculateShadeTint
  c.tintHSBColor[0]: 26 c.shadeHSBColor[0]: 26
  c.tintHSBColor[1]: 255 c.shadeHSBColor[1]: 0
  c.tintHSBColor[2]: 255 c.shadeHSBColor[2]: 0
- function updateInterpolation
  c.tintHSBColor[0]: 1536 c.shadeHSBColor[0]: 9734
  c.tintHSBColor[1]: 38 c.shadeHSBColor[1]: -18426
  c.tintHSBColor[2]: 0 c.shadeHSBColor[2]: 19974

- function ColourAtRYBWheel result: 131,255,255
- function calculateShadeTint
  c.tintHSBColor[0]: 131 c.shadeHSBColor[0]: 131
  c.tintHSBColor[1]: 255 c.shadeHSBColor[1]: 0
  c.tintHSBColor[2]: 255 c.shadeHSBColor[2]: 0
- function updateInterpolation
  c.tintHSBColor[0]: 1791 c.shadeHSBColor[0]: 1025
  c.tintHSBColor[1]: 1236 c.shadeHSBColor[1]: 0
  c.tintHSBColor[2]: 1061 c.shadeHSBColor[2]: -512

- function ColourAtRYBWheel result: 92,255,255
- function calculateShadeTint
  c.tintHSBColor[0]: 92 c.shadeHSBColor[0]: 92
  c.tintHSBColor[1]: 255 c.shadeHSBColor[1]: 0
  c.tintHSBColor[2]: 255 c.shadeHSBColor[2]: 0
- function updateInterpolation
  c.tintHSBColor[0]: 6913 c.shadeHSBColor[0]: 1280
  c.tintHSBColor[1]: 614 c.shadeHSBColor[1]: 19459
  c.tintHSBColor[2]: -6656 c.shadeHSBColor[2]: 11776

- function ColourAtRYBWheel result: 188,255,255
- function calculateShadeTint
  c.tintHSBColor[0]: 188 c.shadeHSBColor[0]: 188
  c.tintHSBColor[1]: 255 c.shadeHSBColor[1]: 0
  c.tintHSBColor[2]: 255 c.shadeHSBColor[2]: 0
- function updateInterpolation
  c.tintHSBColor[0]: 0 c.shadeHSBColor[0]: 0
  c.tintHSBColor[1]: 0 c.shadeHSBColor[1]: 0
  c.tintHSBColor[2]: 0 c.shadeHSBColor[2]: 0

Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 638
Posts: 50304
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

One of the tools I use on a regular basis is a code auditor. One of the things it insists on is that a constructor provide an initial value to every class member. Your ColourBase constructor does not provide initial values for the wheelHSBColor, tintHSBColor, shadeHSBColor or interpolatedHSBColor arrays or the RGB fields.

Do you still get the same (as yet unclear to me why they are) wrong results if you do provide initial values for these arrays and members?
Logged

Enschede - The Netherlands
Offline Offline
Jr. Member
**
Karma: 0
Posts: 75
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't get the strange readings when I init like this:

Code:
ColourBase::ColourBase()
{ interpolation = 0.5;
baseHue = 0;

for (int i=0;i<3; i++)
{
wheelHSBColor[i]        = 1;
tintHSBColor[i]         = 1;
shadeHSBColor[i]        = 1;
interpolatedHSBColor[i] = 1; // interpolated color between shade/tint
}

wheelRGBColor = 0;   
    shadeRGBColor = 0;
    tintRGBColor  = 0;   
    interpolatedRGBColor = 0;

Serial.println("constructor colourbase");
}

I've found out that the values are not set then in the updateInterpolation function:
Code:
constructor colourbase
constructor colourbase
constructor colourbase
constructor colourbase
constructor colourbase
constructor colourbase
- function update palette

- function ColourAtRYBWheel result: 4,255,255
- function calculateShadeTint
  c.tintHSBColor[0]: 4 c.shadeHSBColor[0]: 4
  c.tintHSBColor[1]: 128 c.shadeHSBColor[1]: 128
  c.tintHSBColor[2]: 128 c.shadeHSBColor[2]: 128
- function updateInterpolation
  c.tintHSBColor[0]: 1 c.shadeHSBColor[0]: 1
  c.tintHSBColor[1]: 1 c.shadeHSBColor[1]: 1
  c.tintHSBColor[2]: 1 c.shadeHSBColor[2]: 1

- function ColourAtRYBWheel result: 321,255,255
- function calculateShadeTint
  c.tintHSBColor[0]: 321 c.shadeHSBColor[0]: 321
  c.tintHSBColor[1]: 128 c.shadeHSBColor[1]: 128
  c.tintHSBColor[2]: 128 c.shadeHSBColor[2]: 128
- function updateInterpolation
  c.tintHSBColor[0]: 1 c.shadeHSBColor[0]: 1
  c.tintHSBColor[1]: 1 c.shadeHSBColor[1]: 1
  c.tintHSBColor[2]: 1 c.shadeHSBColor[2]: 1

- function ColourAtRYBWheel result: 26,255,255
- function calculateShadeTint
  c.tintHSBColor[0]: 26 c.shadeHSBColor[0]: 26
  c.tintHSBColor[1]: 128 c.shadeHSBColor[1]: 128
  c.tintHSBColor[2]: 128 c.shadeHSBColor[2]: 128
- function updateInterpolation
  c.tintHSBColor[0]: 1 c.shadeHSBColor[0]: 1
  c.tintHSBColor[1]: 1 c.shadeHSBColor[1]: 1
  c.tintHSBColor[2]: 1 c.shadeHSBColor[2]: 1

- function ColourAtRYBWheel result: 131,255,255
- function calculateShadeTint
  c.tintHSBColor[0]: 131 c.shadeHSBColor[0]: 131
  c.tintHSBColor[1]: 128 c.shadeHSBColor[1]: 128
  c.tintHSBColor[2]: 128 c.shadeHSBColor[2]: 128
- function updateInterpolation
  c.tintHSBColor[0]: 1 c.shadeHSBColor[0]: 1
  c.tintHSBColor[1]: 1 c.shadeHSBColor[1]: 1
  c.tintHSBColor[2]: 1 c.shadeHSBColor[2]: 1

- function ColourAtRYBWheel result: 92,255,255
- function calculateShadeTint
  c.tintHSBColor[0]: 92 c.shadeHSBColor[0]: 92
  c.tintHSBColor[1]: 128 c.shadeHSBColor[1]: 128
  c.tintHSBColor[2]: 128 c.shadeHSBColor[2]: 128
- function updateInterpolation
  c.tintHSBColor[0]: 1 c.shadeHSBColor[0]: 1
  c.tintHSBColor[1]: 1 c.shadeHSBColor[1]: 1
  c.tintHSBColor[2]: 1 c.shadeHSBColor[2]: 1

- function ColourAtRYBWheel result: 188,255,255
- function calculateShadeTint
  c.tintHSBColor[0]: 188 c.shadeHSBColor[0]: 188
  c.tintHSBColor[1]: 128 c.shadeHSBColor[1]: 128
  c.tintHSBColor[2]: 128 c.shadeHSBColor[2]: 128
- function updateInterpolation
  c.tintHSBColor[0]: 1 c.shadeHSBColor[0]: 1
  c.tintHSBColor[1]: 1 c.shadeHSBColor[1]: 1
  c.tintHSBColor[2]: 1 c.shadeHSBColor[2]: 1

However I tried to call the updateInterpolation function from the calculateShadeTint function like this.
Code:
updateInterpolation(c); 
and removed it from this for-loop
Code:
for (int i=0; i<6;i++)
{ // convert to new hue numbers with the new ColorWheel (HueToRYB)
    ColourAtRYBWheel(cArray[i].baseHue, cArray[i].wheelHSBColor);
    calculateShadeTint(cArray[i]); 
    //updateInterpolation(cArray[i]); 
}

And now I get the right values.
Code:
- function ColourAtRYBWheel result: 4,255,255
- function calculateShadeTint
  c.tintHSBColor[0]: 4 c.shadeHSBColor[0]: 4
  c.tintHSBColor[1]: 128 c.shadeHSBColor[1]: 128
  c.tintHSBColor[2]: 128 c.shadeHSBColor[2]: 128
- function updateInterpolation
  c.tintHSBColor[0]: 4 c.shadeHSBColor[0]: 4
  c.tintHSBColor[1]: 128 c.shadeHSBColor[1]: 128
  c.tintHSBColor[2]: 128 c.shadeHSBColor[2]: 128
.... etc

But its seems strange to me that it doesn't work in the other way, since Arduino has no threading I think and walks through the code in a lineair way?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 638
Posts: 50304
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I've found out that the values are not set then in the updateInterpolation function
Now that you know what doesn't work, and have a clue as to why, it will be much easier to find a solution.

So, look at the calculateShadeTint() method. The input to the function is an instance of the ColourBase class. Notice that it is NOT a pointer to an instance or a reference to an instance. What does this mean? It means that the ColourBase class' copy constructor was called, and a COPY of the instance was passed to the function. The copy was modified and discarded when the function ended.

You say you didn't define a copy constructor? No matter. The compiler noticed that, and created one for you. What does that copy constructor do? No telling, really.

So, what do you need to do? You need to redefine the class to take a reference to a ColourBase object or a pointer to a ColourBase object. The reference is easiest.

Code:
void calculateShadeTint(ColourBase &c);

void ColourPalette::calculateShadeTint(ColourBase &c)
{
  // The code remains the same
}

The call to the function remains the same, too.

The difference is that the copy constructor will no longer be invoked, and the passed in object WILL be modified, and the modifications will persist when the function ends.
Logged

Pages: 1 [2]   Go Up
Jump to: