annotate grid.mm @ 49:178642d134a7 tip

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