annotate grid.mm @ 45:c2fffc8ea84d

10 timbre params.
author Robert Tubb <rt300@eecs.qmul.ac.uk>
date Tue, 23 Apr 2013 18:29:55 +0100
parents a1e75b94c505
children 1e266647840d
rev   line source
rt300@4 1 //
rt300@4 2 // grid.cpp
rt300@4 3 // oscSenderExample
rt300@4 4 //
rt300@4 5 // Created by Robert Tubb on 03/10/2012.
rt300@4 6 //
rt300@37 7 // This is the grid view, i.e. the viewable representation of hilbert surface
rt300@4 8
rt300@4 9 #include "grid.h"
rt300@4 10
rt300@4 11
rt300@4 12 #include <sstream>
rt300@4 13
rt300@4 14 extern PresetManager presetManager;
rt300@4 15 extern EventLogger eventLogger;
rt300@34 16 extern Hilbert hilbert;
rt300@4 17 //--------------------------------------------------------------
rt300@43 18 Grid::Grid(): minValue(30), paramsPerDim(5), paramBitDepth(7), hilbert(){
rt300@4 19
rt300@37 20 interpLevel = 4;
rt300@4 21 }
rt300@4 22 //--------------------------------------------------------------
rt300@4 23 //--------------------------------------------------------------
rt300@4 24 Grid::~Grid(){
rt300@4 25
rt300@4 26 }
rt300@4 27 void Grid::init(){
rt300@44 28 presetWasTapped = false;
rt300@43 29 maxValue = pow(2.0,paramsPerDim*paramBitDepth)-1;
rt300@38 30 interpolateMode = NO_INTERPOLATION;
rt300@37 31
rt300@4 32 maxZoom = false;
rt300@4 33 minZoom = false;
rt300@4 34
rt300@43 35 midiCC = vector<int>(paramsPerDim*2,0);
rt300@43 36
rt300@4 37 pixSize.setCoord(ofGetWidth(), ofGetHeight());
rt300@4 38
rt300@39 39 //set scale to random
rt300@39 40 double scaleLevel = (ofRandomf() + 1.00001)*0.5*paramBitDepth;
rt300@39 41 scale = pow(2.0, scaleLevel*paramBitDepth);
rt300@35 42
rt300@37 43 smallestGridSpacing = 3; //pixels
rt300@37 44
rt300@8 45 snapDist = TwoVector(9,9);
rt300@5 46 snapped = false;
rt300@4 47
rt300@4 48 size.setCoord(pixSize.x*scale, pixSize.y*scale);
rt300@4 49 centre.setCoord(maxValue/2 , maxValue/2);
rt300@4 50 topLeft.setCoord(centre.x - size.x/2, centre.y - size.y/2);
rt300@34 51
rt300@43 52 // do this now
rt300@43 53 hilbert.changeCurve(paramBitDepth, paramsPerDim);
rt300@4 54
rt300@4 55 // set a starting param value, find coord that does it.
rt300@4 56 vector<int> params(paramsPerDim*2);
rt300@4 57 for(int i = 0;i<2*paramsPerDim;i++){
rt300@4 58 midiCC[i] = 12;
rt300@4 59 params[i] = 12;
rt300@4 60 }
rt300@35 61
rt300@35 62
rt300@4 63 TwoVector coord = calculateCoordFromParams(params);
rt300@4 64 setCoord(coord);
rt300@4 65
rt300@4 66 viewWasChanged();
rt300@37 67 calculateInterpolateLevel();
rt300@39 68
rt300@39 69 // log the starting zoom level
rt300@43 70 eventLogger.logEvent(ZOOM,getCoord(), scale);
rt300@43 71
rt300@43 72
rt300@43 73 ///////// TEST HILBERT
rt300@43 74
rt300@43 75
rt300@43 76 /*
rt300@43 77 Hilbert hilbert1(7,1);
rt300@43 78
rt300@43 79 unsigned long long inCoord = 100;
rt300@43 80 vector<int> checkParam;
rt300@43 81 checkParam = hilbert1.calculateParamsFromIndex(inCoord);
rt300@43 82 cout << "PARAMS: ";
rt300@43 83 for(int i=0; i<4;i++){
rt300@43 84 cout << checkParam[i] << " ";
rt300@43 85 }
rt300@43 86 cout << '\n';
rt300@43 87 unsigned long long outCoord = hilbert1.calculateIndexFromParams(checkParam);
rt300@43 88 cout << "UNIT TEST COORD = " << outCoord << "\n";
rt300@43 89 */
rt300@39 90
rt300@4 91 }
rt300@39 92 //--------------------------------------------------------------
rt300@4 93 template <typename T> int sgn(T val) {
rt300@4 94 return (T(0) < val) - (val < T(0));
rt300@4 95 }
rt300@43 96 //--------------------------------------------------------------
rt300@43 97 void Grid::changeNumberOfParamsPerDim(){
rt300@43 98 // experimental func
rt300@43 99 // try using different gray code, etc etc
rt300@43 100 paramsPerDim = 4;
rt300@43 101
rt300@43 102 }
rt300@37 103 //--------------------------------------------------------------
rt300@38 104 double Grid::calculateInterpolateLevel(){
rt300@37 105 if(interpolateMode == INTERPOLATE_GRID){
rt300@38 106
rt300@38 107 // log_32 of scale times the pixel size we want to be the "integral" interp
rt300@38 108 int N = 1 << paramsPerDim;
rt300@38 109 interpLevel = log(scale*N*smallestGridSpacing)/log(N);
rt300@38 110
rt300@38 111 return interpLevel;
rt300@37 112 }else{
rt300@37 113 interpLevel = 0;
rt300@37 114 return 0; // ???
rt300@37 115 }
rt300@37 116 }
rt300@37 117 //--------------------------------------------------------------
rt300@39 118 TwoVector Grid::getCoordForPresetSave(){ // bad functions get bad names
rt300@39 119
rt300@39 120 //
rt300@39 121 TwoVector coord = calculateCoordFromParams(getParams());
rt300@39 122 return coord;
rt300@39 123
rt300@39 124 }
rt300@39 125 //--------------------------------------------------------------
rt300@39 126 void Grid::setScale(double scaleLevel){
rt300@39 127
rt300@39 128 // random
rt300@39 129 //double p = scaleLevel*paramBitDepth*paramsPerDim*0.5;
rt300@39 130
rt300@39 131
rt300@39 132 if(scaleLevel > paramBitDepth || scaleLevel < 0){
rt300@39 133 cout << "Error: Bad scale level: " << scaleLevel << "\n";
rt300@43 134 scaleLevel = round(paramBitDepth*0.5);
rt300@39 135 }
rt300@39 136
rt300@39 137 scale = pow(2.0, scaleLevel*paramsPerDim);
rt300@39 138
rt300@39 139 // update view size using centre
rt300@39 140 // and scale...
rt300@39 141 size.x = ofGetWidth()*scale; // zooming in, size gets SMALLER (view less)
rt300@39 142 size.y = ofGetHeight()*scale;
rt300@39 143
rt300@39 144
rt300@39 145
rt300@39 146 viewWasChanged();
rt300@39 147 calculateInterpolateLevel();
rt300@43 148 eventLogger.logEvent(ZOOM, getCoord(), scale);
rt300@39 149 }
rt300@39 150 //--------------------------------------------------------------
rt300@38 151 void Grid::setInterpolation(interpolateModeType mode){
rt300@38 152 interpolateMode = mode;
rt300@38 153 viewWasChanged();
rt300@38 154 calculateInterpolateLevel();
rt300@38 155 eventLogger.clearTrail();
rt300@38 156 }
rt300@38 157 //--------------------------------------------------------------
rt300@37 158 void Grid::draw(){
rt300@37 159 if(interpolateMode == NO_INTERPOLATION){
rt300@37 160 drawGridLines();
rt300@37 161 drawPresets();
rt300@37 162 }else if(interpolateMode == INTERPOLATE_GRID){
rt300@37 163 // calculate according to smallest gridlines
rt300@37 164 drawGridLines();
rt300@37 165
rt300@37 166 }else if(interpolateMode == INTERPOLATE_PRESET){
rt300@37 167 drawPresets();
rt300@37 168 return; // ???
rt300@37 169 }
rt300@37 170
rt300@37 171
rt300@37 172
rt300@37 173 // draw centre cross hairs
rt300@37 174 drawCrossHairs();
rt300@37 175
rt300@37 176
rt300@37 177 // draw the undo history trail, given viewing area
rt300@37 178 eventLogger.drawTrail(topLeft, topLeft + size);
rt300@37 179 }
rt300@4 180 //--------------------------------------------------------------
rt300@37 181 void Grid::drawGridLines(){ // draw lines
rt300@4 182 // TODO too friggin long
rt300@4 183
rt300@16 184 pixSize.setCoord(ofGetWidth(), ofGetHeight()); // incase of rotation?
rt300@37 185
rt300@4 186 int power = 0;
rt300@4 187
rt300@4 188 // these get big!
rt300@4 189 double divsr;
rt300@4 190 double yl,xl;
rt300@4 191 double gridSize = 0;
rt300@4 192
rt300@4 193 double firstLineXPos, lastLineXPos,firstLineYPos, lastLineYPos, remleft, xoffset, yoffset = 0.0;
rt300@4 194 double xstart, xfinish, ystart,yfinish;
rt300@4 195 // these don't
rt300@4 196 int xpos, ypos = 0;
rt300@4 197
rt300@4 198 float alpha;
rt300@4 199 bool done = false;
rt300@37 200 float markpow = 1 << paramsPerDim; // power that denotes next grid markings e.g. 32
rt300@4 201 int lineWidth = 0;
rt300@4 202 int colCycle = 0;
rt300@4 203
rt300@4 204
rt300@37 205 // loop thru powers of (base?) smallest to biggest
rt300@37 206 // to determine which should be shown as grids
rt300@4 207 while (!done){
rt300@4 208 gridSize = pow(markpow,power);
rt300@4 209
rt300@37 210 colCycle = power % paramBitDepth;
rt300@4 211
rt300@4 212 divsr = size.x / gridSize;
rt300@4 213
rt300@4 214 // if (divisor i.e. number of lines is less than 1000
rt300@37 215 if( ofGetWidth()/divsr >= smallestGridSpacing){
rt300@4 216
rt300@4 217 // calculate transparency
rt300@37 218 float visCont = log10(divsr*2); // 0 if only 1 line, 3 if 1000 lines
rt300@4 219 alpha = 90*(3 - visCont);
rt300@4 220 ofSetLineWidth(lineWidth);
rt300@4 221
rt300@4 222 // cycle colors for different scales
rt300@4 223 if(colCycle == 0){
rt300@4 224 ofSetColor(255,255,255,alpha);
rt300@4 225 }else if(colCycle == 1){
rt300@44 226 ofSetColor(75,0,130,alpha);
rt300@4 227 }else if(colCycle == 2){
rt300@4 228 ofSetColor(0,0,255,alpha);
rt300@4 229 }else if(colCycle == 3){
rt300@4 230 ofSetColor(0,255,0,alpha);
rt300@4 231 }else if(colCycle == 4){
rt300@44 232 ofSetColor(255,255,0,alpha);
rt300@4 233 }else if(colCycle == 5){
rt300@44 234 ofSetColor(255,127,0,alpha);
rt300@4 235 }else if(colCycle == 6){
rt300@44 236 ofSetColor(255,0,0,alpha);
rt300@4 237 }else if(colCycle == 7){
rt300@44 238 ofSetColor(255,255,255,255);
rt300@4 239 }else{
rt300@44 240 ofSetColor(255,255,255,255);
rt300@43 241 cout << "colour cycle > 7\n";
rt300@4 242 }
rt300@4 243
rt300@4 244
rt300@4 245 // draw level numbers associated with each color. This would not be true if markpow wasnt 2^d
rt300@4 246 ////////-------/////////
rt300@4 247 /*
rt300@4 248 temp << "THIS LEVEL = " << (int)pow(2.0,power) << " ";
rt300@4 249 string s = temp.str();
rt300@4 250 ofDrawBitmapString( s, 10, line );
rt300@4 251 line+=30;
rt300@4 252 temp.str("");
rt300@4 253 *////////-------/////////
rt300@4 254
rt300@4 255 // draw presets at this level
rt300@4 256 // fill in smallest squares if they contain a preset
rt300@4 257 // how to do this efficiently?
rt300@4 258
rt300@4 259
rt300@4 260 if(topLeft.x < 0.0){
rt300@4 261 firstLineXPos = 0.0;
rt300@4 262 xoffset = firstLineXPos - topLeft.x;
rt300@4 263 xstart = xoffset/scale;
rt300@4 264 }else{
rt300@4 265 firstLineXPos = topLeft.x;
rt300@4 266 // kinda float version of % operator
rt300@4 267 remleft = ceil(firstLineXPos/gridSize);
rt300@4 268 xoffset = (remleft * gridSize) - topLeft.x;
rt300@4 269 xstart = 0;
rt300@4 270 }
rt300@4 271 if(topLeft.x + size.x > maxValue){
rt300@4 272 lastLineXPos = maxValue+1 - topLeft.x;
rt300@4 273
rt300@4 274
rt300@4 275 }else{
rt300@4 276 lastLineXPos = size.x;
rt300@4 277
rt300@4 278 }
rt300@4 279 xfinish = lastLineXPos/scale;
rt300@4 280
rt300@4 281 //////////------------------------
rt300@4 282 // same for y
rt300@4 283
rt300@4 284 if(topLeft.y < 0.0){
rt300@4 285 firstLineYPos = 0.0;
rt300@4 286 yoffset = firstLineYPos - topLeft.y;
rt300@4 287 ystart = yoffset/scale;
rt300@4 288 }else{
rt300@4 289 firstLineYPos = topLeft.y;
rt300@4 290 // kinda float version of % operator
rt300@4 291 remleft = ceil(firstLineYPos/gridSize);
rt300@4 292 yoffset = (remleft * gridSize) - topLeft.y;
rt300@4 293 ystart = 0;
rt300@4 294 }
rt300@4 295 if(topLeft.y + size.y > maxValue){
rt300@4 296 lastLineYPos = maxValue+1 - topLeft.y;
rt300@4 297
rt300@4 298 }else{
rt300@4 299 lastLineYPos = size.y;
rt300@4 300
rt300@4 301 }
rt300@4 302 yfinish = lastLineYPos/scale;
rt300@4 303 // -------------------------------------------
rt300@4 304 // now draw
rt300@4 305 for(xl = xoffset; xl <= (lastLineXPos); xl+= gridSize){
rt300@4 306
rt300@4 307 xpos = xl/scale;
rt300@4 308 ofLine(xpos, ystart, xpos, yfinish);
rt300@4 309
rt300@4 310 }
rt300@4 311
rt300@4 312 for(yl = yoffset; yl <= (lastLineYPos); yl+= gridSize){
rt300@4 313
rt300@4 314 ypos = yl/scale;
rt300@4 315 ofLine(xstart, ypos, xfinish, ypos);
rt300@4 316 }
rt300@4 317
rt300@4 318
rt300@37 319 }
rt300@37 320 /*else if (divsr < 1){
rt300@37 321 // maximum only one line. worth checking so that bigger lines still show up?
rt300@4 322 done = true;
rt300@4 323 }
rt300@37 324 */
rt300@4 325 power++;
rt300@37 326 if(power > paramBitDepth)
rt300@37 327 done = true;
rt300@37 328
rt300@4 329 }
rt300@4 330 //cout << "draw done" << "\n";
rt300@4 331 //displayInfo();
rt300@4 332
rt300@33 333
rt300@33 334
rt300@4 335 ////////-------////////
rt300@4 336 /*
rt300@4 337 ostringstream temp;
rt300@4 338 temp << "Centre x = " << centre.x << "\n y = " << centre.y << " ";
rt300@4 339 string s = temp.str();
rt300@4 340 ofDrawBitmapString( s, pixSize.x/2+10, pixSize.y/2+10 );
rt300@4 341 */
rt300@4 342 }
rt300@5 343 //-----------------------------------------------------------------------
rt300@5 344 void Grid::drawCrossHairs(){
rt300@5 345 // snapping
rt300@5 346 TwoVector pos;
rt300@5 347 if(snapped){
rt300@5 348 pos = coordToPixel(snapCentre);
rt300@5 349 }else{
rt300@5 350 pos = coordToPixel(centre);
rt300@5 351
rt300@5 352 }
rt300@5 353 ofSetColor(255, 0, 0);
rt300@5 354 ofNoFill();
rt300@5 355 ofLine(pos.x-20, pos.y, pos.x+20, pos.y);
rt300@5 356 ofLine(pos.x, pos.y-20, pos.x, pos.y+20);
rt300@5 357 ofEllipse(pos.x, pos.y, 20, 20);
rt300@5 358 ofFill();
rt300@5 359 }
rt300@5 360 //-----------------------------------------------------------------------
rt300@4 361 TwoVector Grid::coordToPixel(TwoVector coord){
rt300@4 362 TwoVector pix;
rt300@4 363 pix.x = (coord.x - topLeft.x)/scale;
rt300@4 364 pix.y = (coord.y - topLeft.y)/scale;
rt300@4 365 return pix;
rt300@4 366
rt300@4 367 }
rt300@44 368 //-----------------------------------------------------------------------
rt300@44 369 TwoVector Grid::pixelToCoord(TwoVector pixel){
rt300@4 370
rt300@44 371 return pixel*scale + topLeft;
rt300@44 372
rt300@44 373 }
rt300@4 374 //-----------------------------------------------------------------------
rt300@4 375 void Grid::drawPresets(){
rt300@5 376 presetManager.drawPresetsInRange(topLeft, topLeft + size);
rt300@7 377 // draw snapped preset info
rt300@44 378 if(tappedPreset && tappedPreset != NULL){
rt300@44 379 TwoVector presetPos = coordToPixel(tappedPreset->coordinates);
rt300@44 380 ofDrawBitmapString( tappedPreset->displayTextDescription(), presetPos.x, presetPos.y );
rt300@44 381 }else if( (snapped) && closestPreset != NULL){
rt300@44 382 ofDrawBitmapString( closestPreset->displayTextDescription(), pixSize.x/2 +10, pixSize.y/2+10 );
rt300@7 383 }
rt300@44 384
rt300@33 385
rt300@4 386 }
rt300@4 387
rt300@4 388 //-----------------------------------------------------------------------
rt300@4 389 void Grid::displayInfo(){
rt300@4 390
rt300@4 391 // display some "useful information"
rt300@4 392
rt300@4 393 ofSetColor(255,255,255,255);
rt300@4 394
rt300@4 395 ostringstream temp;
rt300@4 396 int line = 10; // text output pos
rt300@4 397
rt300@4 398
rt300@4 399 ////////-------/////////
rt300@4 400 temp << "scale = " << scale << " ";
rt300@4 401 string s = temp.str();
rt300@4 402 ofDrawBitmapString( s, 10, line );
rt300@4 403 line+=30;
rt300@4 404 temp.str("");
rt300@4 405 ////////-------/////////
rt300@4 406 temp << "Top Left = " << topLeft.x << "," << topLeft.y << " ";
rt300@4 407 s = temp.str();
rt300@4 408 ofDrawBitmapString( s, 10, line );
rt300@4 409 line+=60;
rt300@4 410 temp.str("");
rt300@4 411
rt300@4 412 ////////-------/////////
rt300@4 413 temp << "View Size = " << size.x << "," << size.y << " ";
rt300@4 414 s = temp.str();
rt300@4 415 ofDrawBitmapString( s, 10, line );
rt300@4 416 line+=60;
rt300@4 417 temp.str("");
rt300@4 418
rt300@4 419 ////////-------/////////
rt300@4 420
rt300@43 421 for(int i=0;i<2*paramsPerDim;i++){ // TODO 5bit specific
rt300@4 422 temp << midiCC[i] << " ";
rt300@4 423 s = temp.str();
rt300@4 424 ofDrawBitmapString( s, 10, line );
rt300@4 425 line+=20;
rt300@4 426 temp.str("");
rt300@4 427 }
rt300@4 428 }
rt300@4 429 //--------------------------------------------------------------
rt300@4 430 void Grid::update(){ // ?
rt300@4 431
rt300@4 432
rt300@4 433 }
rt300@44 434 //--------------------------------------------------------------
rt300@44 435 void Grid::tap(TwoVector pixel){
rt300@44 436 static Preset * lastTappedPreset;
rt300@44 437
rt300@44 438 // search nearby for preset
rt300@44 439 TwoVector tapCoord = pixelToCoord(pixel);
rt300@44 440
rt300@44 441 vector<Preset *> closePresets = presetManager.getPresetsInRange(tapCoord - snapDist*2*scale, tapCoord + snapDist*2*scale);
rt300@44 442 if(closePresets.size() > 0){
rt300@44 443 tappedPreset = getClosestPresetOf(closePresets);
rt300@44 444 //interpolateTo(coordinates);
rt300@44 445 cout << "tapped preset: " << tappedPreset->name << "\n";
rt300@44 446 presetWasTapped = true;
rt300@44 447
rt300@44 448 if(lastTappedPreset == tappedPreset){
rt300@44 449 cout << "DOUBLE tapped preset: " << tappedPreset->name << "\n";
rt300@44 450
rt300@44 451 //TODO interpolate to this! exciting!
rt300@44 452 setCoord(tappedPreset->coordinates); // should just go there and do all the calcs
rt300@44 453 ((testApp *)ofGetAppPtr())->setAllGUISliders(getParams());
rt300@44 454 eventLogger.logEvent(PRESET_DOUBLE_TAPPED, getCoord(), scale);
rt300@44 455
rt300@44 456
rt300@44 457 }
rt300@44 458
rt300@44 459 lastTappedPreset = tappedPreset;
rt300@44 460 }else{
rt300@44 461 // nothing ?
rt300@44 462 }
rt300@44 463 }
rt300@5 464
rt300@4 465 //--------------------------------------------------------------
rt300@33 466
rt300@4 467 void Grid::move(TwoVector moveP){
rt300@4 468 // numspacing, pixelspacing stay the same
rt300@4 469
rt300@4 470 // convert pixels to surf units
rt300@4 471 TwoVector moveS;
rt300@4 472 moveS = moveP * scale;
rt300@4 473
rt300@4 474 topLeft = topLeft - moveS; // - because moving to the right means taking away from offset
rt300@4 475 centre = centre - moveS;
rt300@4 476
rt300@4 477 viewWasChanged();
rt300@43 478 eventLogger.logEvent(SCROLL, getCoord(), scale);
rt300@4 479
rt300@4 480 }
rt300@4 481 //--------------------------------------------------------------
rt300@4 482 void Grid::zoom(float factor){
rt300@5 483 if(snapped)centre = (centre + snapCentre)*0.5; // clunky
rt300@5 484
rt300@4 485 if(maxZoom && factor > 1.0){
rt300@4 486 return;
rt300@4 487
rt300@4 488 }
rt300@4 489 if(factor < 1.0){
rt300@4 490 maxZoom = false;
rt300@4 491 }
rt300@4 492 if(minZoom && factor < 1.0){
rt300@4 493 return;
rt300@4 494
rt300@4 495 }
rt300@4 496 if(factor > 1.0){
rt300@4 497 minZoom = false;
rt300@4 498 }
rt300@4 499 scale = scale*factor; // simple eh?
rt300@4 500
rt300@4 501 // update view size using centre
rt300@4 502 // and scale...
rt300@4 503 size.x = size.x*factor; // zooming in, size gets SMALLER (view less)
rt300@4 504 size.y = size.y*factor;
rt300@4 505
rt300@4 506
rt300@4 507
rt300@4 508 viewWasChanged();
rt300@37 509 calculateInterpolateLevel();
rt300@43 510 eventLogger.logEvent(ZOOM, getCoord(), scale);
rt300@4 511
rt300@5 512 }
rt300@5 513 //--------------------------------------------------------------
rt300@20 514 void Grid::shiftCentreToSnapped(){
rt300@20 515 // TODO just in case we're freezing something
rt300@20 516 // snapping actually change centre
rt300@20 517 centre = snapCentre;
rt300@20 518
rt300@20 519 }
rt300@20 520 //--------------------------------------------------------------
rt300@44 521 Preset * Grid::getClosestPresetOf(vector<Preset *> somepresets){
rt300@44 522 double dist, mindist = maxValue;
rt300@44 523 Preset * cPreset = somepresets[0];
rt300@44 524
rt300@44 525 for(vector<Preset *>::iterator piter = somepresets.begin(); piter < somepresets.end(); piter++){
rt300@44 526 dist = (*piter)->coordinates.distanceTo(centre);
rt300@44 527
rt300@44 528 if(dist < mindist){
rt300@44 529 mindist = dist;
rt300@44 530 cPreset = (*piter);
rt300@44 531 }
rt300@44 532 }
rt300@44 533 return cPreset;
rt300@44 534 }
rt300@44 535 //--------------------------------------------------------------
rt300@5 536 void Grid::snapCheck(){
rt300@44 537 lEvent *closestEvalPt;
rt300@45 538
rt300@38 539
rt300@5 540 // check environs for presets.
rt300@44 541
rt300@5 542 vector<Preset *> closePresets = presetManager.getPresetsInRange(centre - snapDist*scale, centre + snapDist*scale);
rt300@5 543 if(closePresets.size() > 0){
rt300@45 544 if(interpolateMode == INTERPOLATE_GRID){
rt300@45 545 snapped = false;
rt300@45 546 closestPreset = NULL;
rt300@45 547 snapCentre = centre;
rt300@45 548 return;
rt300@45 549 } // no presets visible
rt300@45 550
rt300@5 551 snapped = true;
rt300@44 552 presetWasTapped = false;
rt300@44 553 closestPreset = getClosestPresetOf(closePresets);
rt300@5 554 snapCentre = closestPreset->coordinates;
rt300@22 555 eventLogger.logEvent(SNAPPED_TO_PRESET, getCoord(),closestPreset->creationTime );
rt300@44 556
rt300@43 557
rt300@5 558 }else{
rt300@45 559 // look for evaluation points
rt300@44 560 // do an evaluation snap check . duplicate code >:[
rt300@44 561
rt300@44 562 vector<lEvent *> closeEvalPoints = eventLogger.getEvaluationPointsInRange(centre - snapDist*scale, centre + snapDist*scale);
rt300@44 563 if(closeEvalPoints.size() > 0){
rt300@44 564 snapped = true;
rt300@44 565
rt300@44 566 double dist, mindist = maxValue;
rt300@44 567 closestEvalPt = closeEvalPoints[0];
rt300@44 568
rt300@44 569 for(vector<lEvent *>::iterator eiter = closeEvalPoints.begin(); eiter < closeEvalPoints.end(); eiter++){
rt300@44 570 TwoVector coord = TwoVector((*eiter)->val1,(*eiter)->val2);
rt300@44 571 dist = coord.distanceTo(centre);
rt300@44 572
rt300@44 573 if(dist < mindist){
rt300@44 574 mindist = dist;
rt300@44 575 closestEvalPt = (*eiter);
rt300@44 576 snapCentre = coord;
rt300@44 577 }
rt300@44 578
rt300@44 579 }
rt300@44 580
rt300@44 581 eventLogger.logEvent(SNAPPED_TO_EVALPT, getCoord() );
rt300@44 582
rt300@44 583 }else{
rt300@44 584 snapped = false;
rt300@44 585 closestPreset = NULL;
rt300@44 586 closestEvalPt = NULL;
rt300@44 587 tappedPreset = NULL;
rt300@44 588 snapCentre = centre;
rt300@44 589 }
rt300@44 590
rt300@44 591
rt300@44 592
rt300@5 593 }
rt300@5 594
rt300@4 595
rt300@4 596 }
rt300@4 597 //--------------------------------------------------------------
rt300@5 598 void Grid::setMaxZoom(){ // got to smallest (white)
rt300@5 599 if(snapped)centre = snapCentre;
rt300@5 600 size.x = maxValue*2.0;
rt300@5 601 scale = size.x/pixSize.x;
rt300@5 602 size.y = scale * pixSize.y;
rt300@7 603 maxZoom = true;
rt300@7 604 minZoom = false;
rt300@5 605 viewWasChanged();
rt300@5 606 }
rt300@5 607 //--------------------------------------------------------------
rt300@5 608 void Grid::setMinZoom(){ // go to entire space (orange)
rt300@5 609 if(snapped)centre = snapCentre;
rt300@5 610 size.x = minValue*2.0;
rt300@5 611 scale = size.x/pixSize.x;
rt300@5 612 size.y = scale * pixSize.y;
rt300@7 613 minZoom = true;
rt300@7 614 maxZoom = false;
rt300@5 615 viewWasChanged();
rt300@4 616 }
rt300@4 617 //--------------------------------------------------------------
rt300@4 618 void Grid::viewWasChanged(){
rt300@5 619 snapCheck();
rt300@4 620 checkLimits();
rt300@5 621 // calculate new params?
rt300@5 622 vector<int> params;
rt300@5 623 if(snapped){
rt300@5 624 params = calculateParamsFromCoord(snapCentre);
rt300@5 625 }else{
rt300@37 626 if(interpolateMode == NO_INTERPOLATION){
rt300@37 627 params = calculateParamsFromCoord(centre);
rt300@37 628 }else if(interpolateMode == INTERPOLATE_GRID){
rt300@37 629 params = calculateInterpolatedParamsFromCoord(centre);
rt300@37 630 }
rt300@5 631 }
rt300@4 632 for(int i = 0;i<2*paramsPerDim;i++){
rt300@4 633 midiCC[i] = params[i];
rt300@4 634 }
rt300@4 635
rt300@4 636 }
rt300@4 637
rt300@4 638 //--------------------------------------------------------------
rt300@4 639 void Grid::checkLimits(){
rt300@4 640 // check for maximum zoom level
rt300@5 641
rt300@4 642
rt300@4 643 if(size.x > maxValue*2.0){
rt300@39 644
rt300@4 645 maxZoom = true;
rt300@4 646 size.x = maxValue*2.0;
rt300@4 647 // need to also set y size back to
rt300@4 648 }
rt300@4 649 if(size.y > maxValue*2.0){
rt300@39 650
rt300@4 651 maxZoom = true;
rt300@4 652 size.y = maxValue*2.0;
rt300@4 653 }
rt300@4 654
rt300@4 655 if(size.x < minValue){
rt300@39 656
rt300@4 657 minZoom = true;
rt300@4 658 size.x = minValue;
rt300@4 659 // need to also set y size back to
rt300@4 660 }
rt300@4 661 if(size.y < minValue){
rt300@4 662 minZoom = true;
rt300@39 663
rt300@4 664 size.y = minValue;
rt300@4 665 }
rt300@4 666
rt300@4 667 scale = size.x/pixSize.x;
rt300@4 668 size.y = scale * pixSize.y;
rt300@4 669
rt300@4 670 topLeft.x = centre.x - size.x/2;
rt300@4 671 topLeft.y = centre.y - size.y/2;
rt300@4 672 // check for negatives
rt300@4 673
rt300@4 674 // allow centre to be at limits
rt300@4 675 if((topLeft.x + size.x*0.5) < 0.0){
rt300@4 676 topLeft.x = 0.0 - size.x*0.5;
rt300@4 677 centre.x = 0.0;
rt300@4 678 }
rt300@4 679
rt300@4 680 if(topLeft.y + size.y*0.5 < 0.0) {
rt300@4 681 topLeft.y = 0.0 - size.y*0.5;
rt300@4 682 centre.y = 0.0;
rt300@4 683 }
rt300@4 684
rt300@4 685 // does topleft refer to lines or view?
rt300@4 686
rt300@4 687 // check max
rt300@4 688 if(topLeft.x + size.x/2 > maxValue){
rt300@4 689 topLeft.x = maxValue - size.x/2;
rt300@4 690 centre.x = maxValue;
rt300@4 691 }
rt300@4 692 if(topLeft.y + size.y/2 > maxValue) {
rt300@4 693 topLeft.y = maxValue - size.y/2;
rt300@4 694 centre.y = maxValue;
rt300@4 695 }
rt300@4 696
rt300@4 697 }
rt300@4 698 //--------------------------------------------------------------
rt300@4 699 void Grid::checkConsistencies(){
rt300@4 700 // debug function to check all the parameters are consistent maybe
rt300@4 701
rt300@4 702 }
rt300@4 703 //--------------------------------------------------------------
rt300@4 704 void Grid::setCoord(TwoVector coord){
rt300@4 705
rt300@4 706 centre = coord;
rt300@5 707
rt300@4 708 viewWasChanged();
rt300@4 709 }
rt300@4 710 //--------------------------------------------------------------
rt300@4 711 TwoVector Grid::getCoord(){
rt300@5 712 // return read point crosshairs
rt300@5 713 if(snapped){
rt300@5 714 return snapCentre;
rt300@5 715 }
rt300@4 716 return centre;
rt300@4 717 }
rt300@4 718 //--------------------------------------------------------------
rt300@4 719 vector<int> Grid::getParams(){
rt300@4 720 // return a vector with midiCCs in
rt300@43 721 // if less than 10, fill rest with zeros
rt300@43 722
rt300@43 723 vector<int> params(10,0);
rt300@4 724 //
rt300@4 725 for(int i = 0;i<2*paramsPerDim;i++){
rt300@4 726 params[i] = midiCC[i];
rt300@4 727 }
rt300@43 728 for(int i = 2*paramsPerDim;i<10;i++){
rt300@43 729 params[i] = 0;
rt300@43 730 }
rt300@4 731 return params;
rt300@4 732 }
rt300@4 733 //--------------------------------------------------------------
rt300@4 734 void Grid::setParams(vector<int> params){
rt300@4 735 // input midiCCs, and go to the appropriate coordinate
rt300@4 736
rt300@4 737 for(int i = 0;i<2*paramsPerDim;i++){
rt300@43 738 midiCC[i] = params[i];
rt300@4 739 }
rt300@4 740 TwoVector coord = calculateCoordFromParams(params);
rt300@4 741 setCoord(coord);
rt300@4 742
rt300@20 743 // snapping?
rt300@4 744 viewWasChanged();
rt300@4 745
rt300@4 746 }
rt300@4 747 //--------------------------------------------------------------
rt300@5 748 //--------------------------------------------------------------
rt300@5 749 //--------------------------------------------------------------
rt300@5 750 //--------------------------------------------------------------
rt300@5 751 //--------------------------------------------------------------
rt300@5 752 #pragma mark const utils
rt300@5 753
rt300@37 754 TwoVector Grid::calculateCoordFromParams(vector<int> params){
rt300@4 755
rt300@4 756 vector<int> ccValueX(paramsPerDim);
rt300@4 757 vector<int> ccValueY(paramsPerDim);
rt300@4 758 for(int i=0;i<paramsPerDim;i++){
rt300@4 759 ccValueX[i] = params[i];
rt300@4 760 ccValueY[i] = params[i+paramsPerDim];
rt300@4 761 }
rt300@4 762
rt300@4 763 TwoVector result;
rt300@35 764 result.x = hilbert.calculateIndexFromParams(ccValueX);
rt300@35 765 result.y = hilbert.calculateIndexFromParams(ccValueY);
rt300@4 766 return result;
rt300@4 767 }
rt300@4 768
rt300@4 769 //--------------------------------------------------------------
rt300@37 770 vector<int> Grid::calculateParamsFromCoord(TwoVector coord){
rt300@35 771
rt300@4 772 if (coord.x > maxValue || coord.y > maxValue){
rt300@4 773 cout << "calculateParams Error: centre double value is too large" << "\n";
rt300@4 774 vector<int> empty;
rt300@4 775 return empty;
rt300@4 776 }
rt300@35 777 if (coord.x < 0 || coord.y < 0){
rt300@35 778 cout << "calculateParams Error: centre double value is negative" << "\n";
rt300@35 779 vector<int> empty;
rt300@35 780 return empty;
rt300@4 781 }
rt300@4 782
rt300@35 783 // X
rt300@35 784 vector<int> resultX;
rt300@35 785 resultX = hilbert.calculateParamsFromIndex(coord.x);
rt300@35 786 // Y
rt300@4 787 vector<int> resultY;
rt300@35 788 resultY = hilbert.calculateParamsFromIndex(coord.y);
rt300@4 789
rt300@4 790 // concatenate
rt300@35 791 vector<int> result = resultX;
rt300@35 792
rt300@4 793 result.insert( result.end(), resultY.begin(), resultY.end() );
rt300@4 794 return result;
rt300@4 795 }
rt300@37 796 //--------------------------------------------------------------
rt300@37 797 vector<int> Grid::calculateInterpolatedParamsFromCoord(TwoVector coord){
rt300@4 798
rt300@37 799 vector<int> result;
rt300@37 800
rt300@38 801 int interpLevelBigGrid = ceil(interpLevel);
rt300@38 802 int interpLevelSmallGrid = floor(interpLevel);
rt300@38 803
rt300@38 804 if(interpLevelBigGrid >= paramBitDepth){
rt300@38 805 // maximum is bit-1 so don't do interp at all
rt300@38 806 vector<int> pSmallGrid = interpHilbert(interpLevelSmallGrid, coord);
rt300@38 807 return pSmallGrid;
rt300@38 808 }
rt300@38 809 double interpFrac = interpLevel - interpLevelSmallGrid;
rt300@38 810
rt300@38 811 vector<int> pBigGrid = interpHilbert(interpLevelBigGrid, coord);
rt300@38 812 vector<int> pSmallGrid = interpHilbert(interpLevelSmallGrid, coord);
rt300@38 813 // now we need to interpolate twixt these two aswell!
rt300@38 814
rt300@38 815 result = interpVector(pBigGrid, pSmallGrid, interpFrac);
rt300@38 816
rt300@38 817 return result;
rt300@38 818 }
rt300@38 819 //--------------------------------------------------------------
rt300@38 820 vector<int> Grid::interpHilbert(int bitlevel, TwoVector coord){
rt300@38 821 vector<int> result;
rt300@37 822 long long x = coord.x;
rt300@37 823 long long y = coord.y;
rt300@38 824
rt300@38 825 int roundDigits = (paramsPerDim*bitlevel);
rt300@37 826 // knock off last digits
rt300@37 827 x = x >> roundDigits;
rt300@37 828 x = x << roundDigits;
rt300@37 829 float frac = (coord.x - x)/(1 << roundDigits);
rt300@37 830 long long xlower = x;
rt300@37 831 long long xupper = x + (1 << roundDigits);
rt300@38 832
rt300@37 833 vector<int> pupper = hilbert.calculateParamsFromIndex(xupper);
rt300@37 834 vector<int> plower = hilbert.calculateParamsFromIndex(xlower);
rt300@37 835
rt300@37 836 result = interpVector(pupper,plower,frac);
rt300@38 837 // now Y
rt300@37 838 y = y >> roundDigits;
rt300@37 839 y = y << roundDigits;
rt300@37 840 frac = (coord.y - y)/(1 << roundDigits);
rt300@37 841 long long ylower = y;
rt300@37 842 long long yupper = y + (1 << roundDigits);
rt300@37 843
rt300@37 844 pupper = hilbert.calculateParamsFromIndex(yupper);
rt300@37 845 plower = hilbert.calculateParamsFromIndex(ylower);
rt300@37 846
rt300@37 847 vector<int> resultY = interpVector(pupper,plower,frac);
rt300@38 848 // stickem together
rt300@37 849 result.insert( result.end(), resultY.begin(), resultY.end() );
rt300@38 850
rt300@37 851 return result;
rt300@37 852 }
rt300@37 853 //--------------------------------------------------------------
rt300@37 854 vector<int> Grid::interpVector(vector<int> upper, vector<int> lower, float frac){
rt300@37 855 vector<int> result;
rt300@37 856 if(upper.size() != lower.size()){
rt300@37 857 cout << "Error: interpVector takes vectors of same length" << "\n";
rt300@37 858 return result;
rt300@37 859 }
rt300@37 860 if(frac > 1){
rt300@37 861 cout << "Error: bad fraction for vector interpolation" << "\n";
rt300@37 862 return result;
rt300@37 863 }
rt300@37 864 int N = upper.size();
rt300@37 865 for(int i=0; i<N; i++){
rt300@37 866 result.push_back(frac*upper[i] + (1-frac)*lower[i]);
rt300@37 867 }
rt300@37 868 return result;
rt300@37 869 }
rt300@4 870 //--------------------------------------------------------------
rt300@4 871 vector<int> Grid::walkDiff(vector<bool> left, vector<bool> right){
rt300@4 872 // horrible
rt300@4 873 vector<int> result(2,0);
rt300@4 874
rt300@4 875 int size = left.size();
rt300@4 876 for(int i = 0; i < size; i++){
rt300@4 877 if(left[i] && !right[i]){ // 1 - 0
rt300@4 878 // dim
rt300@4 879 result[0] = i;
rt300@4 880 result[1] = 1;
rt300@4 881 }else if(!left[i] && right[i]){ // 0 - 1
rt300@4 882 result[0] = i;
rt300@4 883 result[1] = -1;
rt300@4 884 }else{ // equal do nothing
rt300@4 885
rt300@4 886
rt300@4 887 }
rt300@4 888 }
rt300@4 889
rt300@4 890 return result;
rt300@4 891 }
rt300@4 892 //--------------------------------------------------------------
rt300@4 893 //--------------------------------------------------------------
rt300@38 894 //--------------------------------------------------------------
rt300@38 895
rt300@38 896
rt300@38 897 //--------------------------------------------------------------
rt300@38 898 //--------------------------------------------------------------
rt300@38 899 //--------------------------------------------------------------
rt300@38 900 //--------------------------------------------------------------
rt300@38 901 //--------------------------------------------------------------
rt300@43 902 #pragma mark The OLD algorithm
rt300@38 903
rt300@38 904 TwoVector Grid::calculateCoordFromParamsOld(vector<int> params) const{
rt300@38 905
rt300@38 906 vector<int> ccValueX(paramsPerDim);
rt300@38 907 vector<int> ccValueY(paramsPerDim);
rt300@38 908 for(int i=0;i<paramsPerDim;i++){
rt300@38 909 ccValueX[i] = params[i];
rt300@38 910 ccValueY[i] = params[i+paramsPerDim];
rt300@38 911 }
rt300@38 912 vector<vector <bool> > codesX = midiToGray(ccValueX);
rt300@38 913 vector<vector <bool> > codesY = midiToGray(ccValueY);
rt300@38 914
rt300@38 915 vector<int> base32X = codesToBase32(codesX);
rt300@38 916 vector<int> base32Y = codesToBase32(codesY);
rt300@38 917
rt300@38 918 TwoVector result;
rt300@38 919 result.x = base32toCoord(base32X);
rt300@38 920 result.y = base32toCoord(base32Y);
rt300@38 921 return result;
rt300@38 922 }
rt300@38 923
rt300@38 924 //--------------------------------------------------------------
rt300@38 925 vector<int> Grid::calculateParamsFromCoordOld(TwoVector coord) const{
rt300@38 926 // some arrays in reverse order of power from normal numbers! 1,2,4,
rt300@38 927
rt300@38 928 // centre to base 32
rt300@38 929 if (coord.x > maxValue || coord.y > maxValue){
rt300@38 930 cout << "calculateParams Error: centre double value is too large" << "\n";
rt300@38 931 vector<int> empty;
rt300@38 932 return empty;
rt300@38 933 }
rt300@38 934
rt300@38 935 //--------------------------
rt300@38 936 // X
rt300@38 937 vector<int> base32x = coordTobase32(coord.x); // 7 numbers from 0 to 31
rt300@38 938 vector<vector <bool> > grayCodesX;
rt300@38 939
rt300@38 940 int size = base32x.size();
rt300@38 941 for(int i=0;i<size;i++){
rt300@38 942 grayCodesX.push_back(intToGray(base32x[i]));
rt300@38 943 }
rt300@38 944
rt300@38 945 vector<int> result;
rt300@38 946 result = grayToMidi(grayCodesX);
rt300@38 947 //--------------------------
rt300@38 948 // AND FOR Y
rt300@38 949 vector<int> base32y = coordTobase32(coord.y);
rt300@38 950 vector<vector <bool> > grayCodesY;
rt300@38 951
rt300@38 952 size = base32y.size();
rt300@38 953 for(int i=0;i<size;i++){
rt300@38 954 grayCodesY.push_back(intToGray(base32y[i]));
rt300@38 955 }
rt300@38 956
rt300@38 957 vector<int> resultY;
rt300@38 958 resultY = grayToMidi(grayCodesY);
rt300@38 959
rt300@38 960 // concatenate
rt300@38 961 result.insert( result.end(), resultY.begin(), resultY.end() );
rt300@38 962 return result;
rt300@38 963 }
rt300@38 964 //-------------------------------------------------------------------
rt300@38 965
rt300@38 966 // for 1 dimension!!! i.e. call this twice
rt300@38 967 vector<int> Grid::grayToMidi(vector<vector <bool> > grayCodes) const{
rt300@38 968
rt300@38 969 // gray to midi CC values
rt300@38 970 // loop thru the scales to build up a CC number per dimension
rt300@38 971 int midiCCresult[paramsPerDim]; // TODO dims specific
rt300@38 972 for(int i=0;i<paramsPerDim;i++){
rt300@38 973 midiCCresult[i] = 0;
rt300@38 974 }
rt300@38 975
rt300@38 976 int bin = 1;
rt300@38 977 bin = bin << grayCodes.size()-1;
rt300@38 978
rt300@38 979 int midP = 0;
rt300@38 980
rt300@38 981 vector<vector <bool> >::iterator piter = grayCodes.begin();
rt300@38 982 for(;piter < grayCodes.end();piter++){ // each lesser power of 2
rt300@38 983 midP = 0; // reset
rt300@38 984 vector<bool>::iterator diter = (*piter).begin();
rt300@38 985 for(; diter <= (*piter).end();diter++){ // each one is different dimension
rt300@38 986 int ig = int(*diter); // convert binary to int
rt300@38 987 //cout << "ig: " << ig;
rt300@38 988 midiCCresult[midP] += ig*bin; // mult by power of two
rt300@38 989 midP++;
rt300@38 990 }
rt300@38 991 bin = bin >> 1; // next power of 2 down
rt300@38 992
rt300@38 993 }
rt300@38 994
rt300@38 995 // put in vector
rt300@38 996 vector<int> result;
rt300@38 997 for(int i=0;i<paramsPerDim;i++){
rt300@38 998 result.push_back(midiCCresult[i]);
rt300@38 999 }
rt300@38 1000
rt300@38 1001 return result;
rt300@38 1002
rt300@38 1003
rt300@38 1004 }
rt300@38 1005
rt300@38 1006
rt300@38 1007 //--------------------------------------------------------------
rt300@38 1008
rt300@38 1009 vector<bool> Grid::intToGray(int num, int dimToTravel) const{
rt300@38 1010
rt300@38 1011 // dimToTravel - this is the dimension that we want the walk to traverse, i.e. the last non zero digit of the code
rt300@38 1012 // so swap it for 3 to produce correct orientation
rt300@38 1013
rt300@38 1014 // just use look up table... until it gets huuuge.
rt300@38 1015 vector<bool> grayCode = vcode[num];
rt300@38 1016 grayCode[3] = vcode[num][dimToTravel];
rt300@38 1017 grayCode[dimToTravel] = vcode[num][3];
rt300@38 1018 return grayCode;
rt300@38 1019 }
rt300@38 1020 //--------------------------------------------------------------
rt300@38 1021 /*
rt300@38 1022 breaks down float into a base 32 number (2^D)
rt300@38 1023 each of these is converted to gray code
rt300@38 1024 this is then converted to 10 parameters, where each 32-digit becomes separate power of 2
rt300@38 1025 so "zoom" grid 32-patches are converted to 2-scales. 1,2,4,8,16,32,64,(128?) biggest number is 32^7
rt300@38 1026 */
rt300@38 1027 vector<int> Grid::coordTobase32(double value) const{
rt300@38 1028 //double base = 32.0;
rt300@38 1029 if(value < 0.0){
rt300@38 1030 cout << "coordTobase32 error: input value is negative\n";
rt300@38 1031 value = 0.0;
rt300@38 1032 }else if(value > maxValue){
rt300@38 1033 cout << "coordTobase32 error: input value too big!\n";
rt300@38 1034 }
rt300@38 1035 double rem, divdr = 0.0;
rt300@38 1036 int digit32;
rt300@38 1037
rt300@38 1038 // what power of 32 to start at?
rt300@38 1039 int maxpow = 7; // midi cc specific
rt300@38 1040 vector<int> result;
rt300@38 1041
rt300@38 1042 rem = value;
rt300@38 1043 for(;maxpow >=0;maxpow--){
rt300@38 1044 // repeatedly get digit and remainder. This is exactly what we're doing in draw !?... could put all this in one place?
rt300@38 1045 divdr = pow((double)codeLength,(double)maxpow);
rt300@38 1046 digit32 = floor(rem/divdr);
rt300@38 1047 rem = rem - digit32*divdr;
rt300@38 1048 result.push_back(digit32); // array, biggest index is smallest power
rt300@38 1049 }
rt300@38 1050 // at this point rem should be fractional... use for interp?
rt300@38 1051
rt300@38 1052 return result;
rt300@38 1053 }
rt300@38 1054 //--------------------------------------------------------------
rt300@38 1055
rt300@38 1056 vector<int> Grid::codesToBase32(vector<vector<bool> > inCodes) const{
rt300@38 1057 vector<int> result;
rt300@38 1058 for(int i=0;i<paramBitDepth;i++){
rt300@38 1059 result.push_back(grayToInt(inCodes[i]));
rt300@38 1060 }
rt300@38 1061 return result;
rt300@38 1062 }
rt300@38 1063 //--------------------------------------------------------------
rt300@38 1064
rt300@38 1065 int Grid::grayToInt(vector<bool> incode) const{
rt300@38 1066 // look for match in table
rt300@38 1067
rt300@38 1068 int s = vcode.size();
rt300@38 1069
rt300@38 1070 for(int i=0; i<s;i++){ // fill vector
rt300@38 1071 if(vcode[i] == incode){
rt300@38 1072 return i;
rt300@38 1073 }
rt300@38 1074
rt300@38 1075 }
rt300@38 1076 cout << "grayToInt error: no matching code found!";
rt300@38 1077 return -1;
rt300@38 1078 }
rt300@38 1079 //--------------------------------------------------------------
rt300@38 1080 double Grid::base32toCoord(vector<int> base32Digs) const{
rt300@38 1081 // build up the big float from a base 32 number
rt300@38 1082 double result = 0.0;
rt300@38 1083
rt300@38 1084 // what power of 32 to start at?
rt300@38 1085 int mpow = base32Digs.size() - 1; // should be 7...
rt300@38 1086
rt300@38 1087 for(int p=0;p<=mpow;p++){ // biggest index is smallest power
rt300@38 1088 result += ((double)base32Digs[p]) * pow(32.0, (double)mpow-p);
rt300@38 1089
rt300@38 1090 }
rt300@38 1091 return result;
rt300@38 1092
rt300@38 1093 }
rt300@38 1094 //--------------------------------------------------------------
rt300@38 1095 // for 1 dimension - takes in 5 cc params and outputs 7 codes
rt300@38 1096 vector<vector <bool> > Grid::midiToGray(vector<int> ccValue) const{
rt300@38 1097 int pow2 = 1 << (paramBitDepth-1);
rt300@38 1098
rt300@38 1099 vector<int> aCode(paramsPerDim);
rt300@38 1100 vector<vector<int> > theXCodes(paramBitDepth,aCode);
rt300@38 1101
rt300@38 1102 // build up binary gray code representations from the bits of the midi ccs
rt300@38 1103
rt300@38 1104 vector<vector<bool> > theCodes(paramBitDepth, vector<bool>(paramsPerDim));
rt300@38 1105
rt300@38 1106 // x
rt300@38 1107 for(int p=0;p<paramBitDepth;p++){
rt300@38 1108
rt300@38 1109 for(int i=0;i<paramsPerDim;i++){
rt300@38 1110
rt300@38 1111 bool bit = (pow2 == (ccValue[i] & pow2));
rt300@38 1112 theCodes[p][i] = bit;
rt300@38 1113 }
rt300@38 1114 pow2 = pow2 >> 1;
rt300@38 1115
rt300@38 1116 }
rt300@38 1117 return theCodes;
rt300@38 1118 }
rt300@38 1119
rt300@38 1120 //--------------------------------------------------------------
rt300@38 1121 void Grid::makeCode(){
rt300@38 1122
rt300@38 1123 ////////////////////////////////~~~,,,,,,,,.........
rt300@38 1124 ////////// gray code generation
rt300@38 1125 //////
rt300@38 1126 ///
rt300@38 1127 // TODO 5bit specific
rt300@38 1128 // transition sequence.... what a palaver! only need to do once though.
rt300@38 1129
rt300@38 1130 // max MRL
rt300@38 1131 int trans[] = {0,1,2,3,0,4,2,1,0,3,2,1,0,4,2,3,0,1,2,3,0,4,2,1,0,3,2,1,0,4,2,3};
rt300@38 1132 // balanced
rt300@38 1133 int transB[] = {1,2,3,4,5,1,5,2,3,5,2,4,2,3,4,1,4,3,2,3,1,5,3,4,1,5,2,5,3,4,1,3};
rt300@38 1134 for(int i = 0; i<codeLength; i++){
rt300@38 1135 transB[i] = transB[i] - 1;
rt300@38 1136 }
rt300@38 1137
rt300@38 1138 int code[codeLength][paramsPerDim]; // start with normal array
rt300@38 1139
rt300@38 1140
rt300@38 1141
rt300@38 1142 for(int j=0; j<paramsPerDim; j++){
rt300@38 1143 code[0][j] = 0;
rt300@38 1144 }
rt300@38 1145
rt300@38 1146 for(int i=0; i < codeLength-1; i++){ // don't need last 3
rt300@38 1147 transSeq.push_back(trans[i]); // member vector
rt300@38 1148 for(int j=0; j<paramsPerDim; j++){
rt300@38 1149
rt300@38 1150 if (j == abs(trans[i])){
rt300@38 1151 code[i+1][j] = !code[i][j];
rt300@38 1152 }else{
rt300@38 1153 code[i+1][j] = code[i][j];
rt300@38 1154 }
rt300@38 1155 }
rt300@38 1156
rt300@38 1157 }
rt300@38 1158
rt300@38 1159 for(int i=0; i < codeLength; i++){ // fill vector
rt300@38 1160
rt300@38 1161 vcode.push_back(vector<bool>());
rt300@38 1162
rt300@38 1163 for(int j=0; j<paramsPerDim; j++){
rt300@38 1164 vcode[i].push_back(code[i][j]);
rt300@38 1165 }
rt300@38 1166 }
rt300@38 1167 /*
rt300@38 1168 // now try with iterators to print...
rt300@38 1169 vector< vector<bool> >::iterator cit;
rt300@38 1170 //vector<bool>::iterator bit;
rt300@38 1171 vector<bool>::iterator bit;
rt300@38 1172 int i = 0;
rt300@38 1173 for(cit=vcode.begin(); cit!=vcode.end() ; cit++){ // fill vector
rt300@38 1174 i++;
rt300@38 1175 cout << i << " = ";
rt300@38 1176 bit = (*cit).begin();
rt300@38 1177 for(bit=(*cit).begin(); bit!=(*cit).end() ; bit++){
rt300@38 1178
rt300@38 1179 cout << *bit;
rt300@38 1180 }
rt300@38 1181 cout << "\n";
rt300@38 1182
rt300@38 1183 }
rt300@38 1184
rt300@38 1185 // codeToInt unit test
rt300@38 1186 vector<bool> aCode = vcode[12];
rt300@38 1187 int result = grayToInt(aCode);
rt300@38 1188 cout << "GRAY TO INT : " << result << "\n";
rt300@38 1189
rt300@38 1190 cout << "-------------------------------\n";
rt300@38 1191
rt300@38 1192 // base32toFloat unit test
rt300@38 1193
rt300@38 1194 vector<int> test32 = coordTobase32(869437.0);
rt300@38 1195 double cresult = base32toCoord(test32);
rt300@38 1196 cout << "base32toCoord : " << cresult << "\n";
rt300@38 1197
rt300@38 1198 cout << "-------------------------------\n";
rt300@38 1199
rt300@38 1200
rt300@38 1201
rt300@38 1202 // midiToGray unit test
rt300@38 1203
rt300@38 1204 vector<vector<bool> > incodes(paramBitDepth, vector<bool>(paramsPerDim));
rt300@38 1205 for(int i=0;i<7;i++){
rt300@38 1206 incodes[i] = vcode[i+5];
rt300@38 1207 }
rt300@38 1208
rt300@38 1209 vector<int> midiTest;
rt300@38 1210 midiTest = grayToMidi(incodes);
rt300@38 1211 vector<vector<bool> > outcodes = midiToGray(midiTest);
rt300@38 1212
rt300@38 1213 vector< vector<bool> >::iterator cit1;
rt300@38 1214 //vector<bool>::iterator bit;
rt300@38 1215 vector<bool>::iterator bit1;
rt300@38 1216 cout << "midiToGray Unit test\n";
rt300@38 1217 for(int i=0;i<paramBitDepth;i++){ // fill vector
rt300@38 1218
rt300@38 1219 for(int j=0;j<paramsPerDim;j++){
rt300@38 1220
rt300@38 1221 cout << (incodes[i][j] == outcodes[i][j]) << ",";
rt300@38 1222 }
rt300@38 1223 cout << "\n";
rt300@38 1224
rt300@38 1225 }
rt300@38 1226 cout << "-------------------------------\n";
rt300@38 1227
rt300@38 1228
rt300@38 1229 // whole process unit test(?)
rt300@38 1230
rt300@38 1231 TwoVector inCoord(888999777,777666555);
rt300@38 1232 vector<int> checkParam;
rt300@38 1233 checkParam = calculateParamsFromCoord(inCoord);
rt300@38 1234 for(int i=0; i<2*paramsPerDim;i++){
rt300@38 1235 cout << checkParam[i] << "_";
rt300@38 1236 }
rt300@38 1237 TwoVector outCoord = calculateCoordFromParams(checkParam);
rt300@38 1238 cout << "Unit TEst coord = " << outCoord.x << "," << outCoord.y << "\n";
rt300@38 1239 */
rt300@38 1240
rt300@38 1241 }
rt300@38 1242 //--------------------------------------------------------------
rt300@38 1243 //--------------------------------------------------------------
rt300@38 1244 //--------------------------------------------------------------