ofVec3f the closest value in the array

Hello guys,

maybe someone can help me!
I built a struct like this:

struct{
   char id;
   ofVec3f rgb;
}Colors;

I create an array of struct with 255 elements:

Colors col[255];

populated the array of struct like this:

 colors[0].id='\x00'; colors[0].rgb=ofVec3f(0,0,0);
 colors[1].id='\x01'; colors[1].rgb=ofVec3f(0,0,0);
 colors[2].id='\x02'; colors[2].rgb=ofVec3f(0,168,0);
 colors[3].id='\x03'; colors[3].rgb=ofVec3f(0,168,0);
 colors[4].id='\x04'; colors[4].rgb=ofVec3f(168,0,168);
 colors[5].id='\x05'; colors[5].rgb=ofVec3f(168,0,168);
 .....

I have a function that makes a loop on the array “struct Colors” and takes as input a ofVec3f:

char update(ofVec3f col) {
        char id;
        for (int i = 0; i < NUM_CHART_MAP; i++) {
          ofVec3f rgb = colors[i].rgb;
          if(rgb == col) {                          <------------------------------- this if() is wrong!
               id=colors[i].id;
          }
        }
        return id;
}

I want to find within the array of struct the value nearest to ofVec3f input.

excuse me English, I hope I explained.

I wish you happy holidays
Dario :slight_smile:

right now there’s definitely one problem here:

char id; 

it’s not really set to anything. in c++ variables don’t have an initial value, which means that they are set to what ever is in memory at their location. This can lead to spurious values and really hard to debug situations. I can see your code failing when id isn’t set to anything new.

usually what I do it set a variable to a value that’s easy to check against, ie:

int id = -1;

then, I search, and if I find what I want, I set id to that new value. that way I can always check if the return value is -1 and check my logic, etc.

in your case, you might want something like a linear search for the minimum value:

    int closestId = -1;
    float minDist = 100000; // start with a large value;
    for (int i = 0; i < NUM_CHART_MAP; i++) {
      ofVec3f rgb = colors[i].rgb;
      float dist = (rgb - colors[i].rgb).length();
      if(dist < minDist) {                        
           minDist = dist;
           closestId=colors[i].id;
      }
    }
    return closestId;

hope this helps!

1 Like

you can also do:

ofVec3f col;
auto nearest = std::min_element(colors.begin(), colors.end(), [&](Colors&c){
    return c.squareDistance(col);
});

which returns an iterator to nearest element in the original vector so later you can do:

nearest->x = ...;

or

ofVec3f v = *nearest;
2 Likes

Thanks a lot @zach and @arturo, really useful information!

Good day!
Dario