annotate grid.mm @ 33:92dba082d957

Added trail and EVALUATION_POINT event type.
author Robert Tubb <rt300@eecs.qmul.ac.uk>
date Tue, 26 Mar 2013 18:41:42 +0000
parents ab7c86d0f3d8
children 94df2cd72d7b
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@4 7 //
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@4 16 //--------------------------------------------------------------
rt300@4 17 Grid::Grid(): maxValue(pow(32.0,7.0)-1), minValue(60), paramsPerDim(5), paramBitDepth(7){
rt300@4 18
rt300@4 19 }
rt300@4 20 //--------------------------------------------------------------
rt300@4 21 //--------------------------------------------------------------
rt300@4 22 Grid::~Grid(){
rt300@4 23
rt300@4 24 }
rt300@4 25 void Grid::init(){
rt300@4 26 //maxValue = pow(32.0,7.0)-1;
rt300@4 27 //minValue = 60; // number of 1-size divisions at smallest scale
rt300@4 28 maxZoom = false;
rt300@4 29 minZoom = false;
rt300@4 30
rt300@4 31 codeLength = pow(2.0,paramsPerDim);
rt300@4 32
rt300@4 33 pixSize.setCoord(ofGetWidth(), ofGetHeight());
rt300@4 34
rt300@4 35 //set scale and position to mid way
rt300@27 36 scale = 15500.0;
rt300@8 37 snapDist = TwoVector(9,9);
rt300@5 38 snapped = false;
rt300@4 39
rt300@4 40 size.setCoord(pixSize.x*scale, pixSize.y*scale);
rt300@4 41 centre.setCoord(maxValue/2 , maxValue/2);
rt300@4 42 topLeft.setCoord(centre.x - size.x/2, centre.y - size.y/2);
rt300@4 43
rt300@4 44
rt300@4 45 makeCode();
rt300@4 46
rt300@4 47 // set a starting param value, find coord that does it.
rt300@4 48 vector<int> params(paramsPerDim*2);
rt300@4 49 for(int i = 0;i<2*paramsPerDim;i++){
rt300@4 50 midiCC[i] = 12;
rt300@4 51 params[i] = 12;
rt300@4 52 }
rt300@4 53 TwoVector coord = calculateCoordFromParams(params);
rt300@4 54 setCoord(coord);
rt300@4 55
rt300@4 56 viewWasChanged();
rt300@4 57
rt300@33 58 cout << "SIZEOF " << sizeof(long long);
rt300@4 59
rt300@4 60
rt300@4 61 }
rt300@4 62
rt300@4 63 template <typename T> int sgn(T val) {
rt300@4 64 return (T(0) < val) - (val < T(0));
rt300@4 65 }
rt300@5 66 //--------------------------------------------------------------
rt300@4 67 void Grid::makeCode(){
rt300@4 68
rt300@4 69 ////////////////////////////////~~~,,,,,,,,.........
rt300@4 70 ////////// gray code generation
rt300@4 71 //////
rt300@4 72 ///
rt300@4 73 // TODO 5bit specific
rt300@4 74 // transition sequence.... what a palaver! only need to do once though.
rt300@32 75
rt300@32 76 // max MRL
rt300@4 77 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@32 78 // balanced
rt300@32 79 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@32 80 for(int i = 0; i<codeLength; i++){
rt300@32 81 transB[i] = transB[i] - 1;
rt300@32 82 }
rt300@4 83
rt300@4 84 int code[codeLength][paramsPerDim]; // start with normal array
rt300@4 85
rt300@4 86
rt300@4 87
rt300@4 88 for(int j=0; j<paramsPerDim; j++){
rt300@4 89 code[0][j] = 0;
rt300@4 90 }
rt300@4 91
rt300@32 92 for(int i=0; i < codeLength-1; i++){ // don't need last 3
rt300@4 93 transSeq.push_back(trans[i]); // member vector
rt300@4 94 for(int j=0; j<paramsPerDim; j++){
rt300@4 95
rt300@4 96 if (j == abs(trans[i])){
rt300@4 97 code[i+1][j] = !code[i][j];
rt300@4 98 }else{
rt300@4 99 code[i+1][j] = code[i][j];
rt300@4 100 }
rt300@4 101 }
rt300@4 102
rt300@4 103 }
rt300@4 104
rt300@4 105 for(int i=0; i < codeLength; i++){ // fill vector
rt300@4 106
rt300@4 107 vcode.push_back(vector<bool>());
rt300@4 108
rt300@4 109 for(int j=0; j<paramsPerDim; j++){
rt300@4 110 vcode[i].push_back(code[i][j]);
rt300@4 111 }
rt300@4 112 }
rt300@7 113 /*
rt300@4 114 // now try with iterators to print...
rt300@4 115 vector< vector<bool> >::iterator cit;
rt300@4 116 //vector<bool>::iterator bit;
rt300@4 117 vector<bool>::iterator bit;
rt300@4 118 int i = 0;
rt300@4 119 for(cit=vcode.begin(); cit!=vcode.end() ; cit++){ // fill vector
rt300@4 120 i++;
rt300@4 121 cout << i << " = ";
rt300@4 122 bit = (*cit).begin();
rt300@4 123 for(bit=(*cit).begin(); bit!=(*cit).end() ; bit++){
rt300@4 124
rt300@4 125 cout << *bit;
rt300@4 126 }
rt300@4 127 cout << "\n";
rt300@4 128
rt300@4 129 }
rt300@7 130
rt300@4 131 // codeToInt unit test
rt300@4 132 vector<bool> aCode = vcode[12];
rt300@4 133 int result = grayToInt(aCode);
rt300@4 134 cout << "GRAY TO INT : " << result << "\n";
rt300@4 135
rt300@4 136 cout << "-------------------------------\n";
rt300@4 137
rt300@4 138 // base32toFloat unit test
rt300@4 139
rt300@4 140 vector<int> test32 = coordTobase32(869437.0);
rt300@4 141 double cresult = base32toCoord(test32);
rt300@4 142 cout << "base32toCoord : " << cresult << "\n";
rt300@4 143
rt300@4 144 cout << "-------------------------------\n";
rt300@4 145
rt300@4 146
rt300@4 147
rt300@4 148 // midiToGray unit test
rt300@4 149
rt300@4 150 vector<vector<bool> > incodes(paramBitDepth, vector<bool>(paramsPerDim));
rt300@4 151 for(int i=0;i<7;i++){
rt300@4 152 incodes[i] = vcode[i+5];
rt300@4 153 }
rt300@4 154
rt300@4 155 vector<int> midiTest;
rt300@4 156 midiTest = grayToMidi(incodes);
rt300@4 157 vector<vector<bool> > outcodes = midiToGray(midiTest);
rt300@4 158
rt300@4 159 vector< vector<bool> >::iterator cit1;
rt300@4 160 //vector<bool>::iterator bit;
rt300@4 161 vector<bool>::iterator bit1;
rt300@4 162 cout << "midiToGray Unit test\n";
rt300@4 163 for(int i=0;i<paramBitDepth;i++){ // fill vector
rt300@4 164
rt300@4 165 for(int j=0;j<paramsPerDim;j++){
rt300@4 166
rt300@4 167 cout << (incodes[i][j] == outcodes[i][j]) << ",";
rt300@4 168 }
rt300@4 169 cout << "\n";
rt300@4 170
rt300@4 171 }
rt300@4 172 cout << "-------------------------------\n";
rt300@4 173
rt300@4 174
rt300@4 175 // whole process unit test(?)
rt300@4 176
rt300@4 177 TwoVector inCoord(888999777,777666555);
rt300@4 178 vector<int> checkParam;
rt300@4 179 checkParam = calculateParamsFromCoord(inCoord);
rt300@4 180 for(int i=0; i<2*paramsPerDim;i++){
rt300@4 181 cout << checkParam[i] << "_";
rt300@4 182 }
rt300@4 183 TwoVector outCoord = calculateCoordFromParams(checkParam);
rt300@4 184 cout << "Unit TEst coord = " << outCoord.x << "," << outCoord.y << "\n";
rt300@4 185 */
rt300@4 186
rt300@4 187 }
rt300@4 188 //--------------------------------------------------------------
rt300@4 189 void Grid::draw(){ // draw lines
rt300@4 190 // TODO too friggin long
rt300@4 191
rt300@16 192 pixSize.setCoord(ofGetWidth(), ofGetHeight()); // incase of rotation?
rt300@4 193 //scale++;
rt300@4 194 // nice loopy thing
rt300@4 195 int power = 0;
rt300@4 196
rt300@4 197 // these get big!
rt300@4 198 double divsr;
rt300@4 199 double yl,xl;
rt300@4 200 double gridSize = 0;
rt300@4 201
rt300@4 202 double firstLineXPos, lastLineXPos,firstLineYPos, lastLineYPos, remleft, xoffset, yoffset = 0.0;
rt300@4 203 double xstart, xfinish, ystart,yfinish;
rt300@4 204 // these don't
rt300@4 205 int xpos, ypos = 0;
rt300@4 206
rt300@4 207 float alpha;
rt300@4 208 bool done = false;
rt300@4 209 float markpow = 32.0; // power that denotes next grid markings
rt300@4 210 int lineWidth = 0;
rt300@4 211 int colCycle = 0;
rt300@4 212
rt300@4 213
rt300@4 214 // loop thru powers of (base?) to determine which should be shown as grids
rt300@4 215 while (!done){
rt300@4 216 gridSize = pow(markpow,power);
rt300@4 217
rt300@4 218 colCycle = power % 7;
rt300@4 219
rt300@4 220 divsr = size.x / gridSize;
rt300@4 221
rt300@4 222 // if (divisor i.e. number of lines is less than 1000
rt300@9 223 if( divsr >= 1 && divsr < 700){
rt300@4 224
rt300@4 225 // calculate transparency
rt300@4 226 float visCont = log10(divsr); // 0 if only 1 line, 3 if 1000 lines
rt300@4 227 alpha = 90*(3 - visCont);
rt300@4 228 ofSetLineWidth(lineWidth);
rt300@4 229
rt300@4 230 // cycle colors for different scales
rt300@4 231 if(colCycle == 0){
rt300@4 232 ofSetColor(255,255,255,alpha);
rt300@4 233 }else if(colCycle == 1){
rt300@4 234 ofSetColor(255,0,0,alpha);
rt300@4 235 }else if(colCycle == 2){
rt300@4 236 ofSetColor(0,0,255,alpha);
rt300@4 237 }else if(colCycle == 3){
rt300@4 238 ofSetColor(0,255,0,alpha);
rt300@4 239 }else if(colCycle == 4){
rt300@4 240 ofSetColor(255,0,255,alpha);
rt300@4 241 }else if(colCycle == 5){
rt300@4 242 ofSetColor(0,255,255,alpha);
rt300@4 243 }else if(colCycle == 6){
rt300@4 244 ofSetColor(255,255,0,alpha);
rt300@4 245 }else if(colCycle == 7){
rt300@4 246 ofSetColor(255,255,255,alpha);
rt300@4 247 }else{
rt300@4 248 cout << "err colour messed up\n";
rt300@4 249 }
rt300@4 250
rt300@4 251
rt300@4 252 // draw level numbers associated with each color. This would not be true if markpow wasnt 2^d
rt300@4 253 ////////-------/////////
rt300@4 254 /*
rt300@4 255 temp << "THIS LEVEL = " << (int)pow(2.0,power) << " ";
rt300@4 256 string s = temp.str();
rt300@4 257 ofDrawBitmapString( s, 10, line );
rt300@4 258 line+=30;
rt300@4 259 temp.str("");
rt300@4 260 *////////-------/////////
rt300@4 261
rt300@4 262 // draw presets at this level
rt300@4 263 // fill in smallest squares if they contain a preset
rt300@4 264 // how to do this efficiently?
rt300@4 265
rt300@4 266
rt300@4 267 if(topLeft.x < 0.0){
rt300@4 268 firstLineXPos = 0.0;
rt300@4 269 xoffset = firstLineXPos - topLeft.x;
rt300@4 270 xstart = xoffset/scale;
rt300@4 271 }else{
rt300@4 272 firstLineXPos = topLeft.x;
rt300@4 273 // kinda float version of % operator
rt300@4 274 remleft = ceil(firstLineXPos/gridSize);
rt300@4 275 xoffset = (remleft * gridSize) - topLeft.x;
rt300@4 276 xstart = 0;
rt300@4 277 }
rt300@4 278 if(topLeft.x + size.x > maxValue){
rt300@4 279 lastLineXPos = maxValue+1 - topLeft.x;
rt300@4 280
rt300@4 281
rt300@4 282 }else{
rt300@4 283 lastLineXPos = size.x;
rt300@4 284
rt300@4 285 }
rt300@4 286 xfinish = lastLineXPos/scale;
rt300@4 287
rt300@4 288 //////////------------------------
rt300@4 289 // same for y
rt300@4 290
rt300@4 291 if(topLeft.y < 0.0){
rt300@4 292 firstLineYPos = 0.0;
rt300@4 293 yoffset = firstLineYPos - topLeft.y;
rt300@4 294 ystart = yoffset/scale;
rt300@4 295 }else{
rt300@4 296 firstLineYPos = topLeft.y;
rt300@4 297 // kinda float version of % operator
rt300@4 298 remleft = ceil(firstLineYPos/gridSize);
rt300@4 299 yoffset = (remleft * gridSize) - topLeft.y;
rt300@4 300 ystart = 0;
rt300@4 301 }
rt300@4 302 if(topLeft.y + size.y > maxValue){
rt300@4 303 lastLineYPos = maxValue+1 - topLeft.y;
rt300@4 304
rt300@4 305 }else{
rt300@4 306 lastLineYPos = size.y;
rt300@4 307
rt300@4 308 }
rt300@4 309 yfinish = lastLineYPos/scale;
rt300@4 310 // -------------------------------------------
rt300@4 311 // now draw
rt300@4 312 for(xl = xoffset; xl <= (lastLineXPos); xl+= gridSize){
rt300@4 313
rt300@4 314 xpos = xl/scale;
rt300@4 315 ofLine(xpos, ystart, xpos, yfinish);
rt300@4 316
rt300@4 317 }
rt300@4 318
rt300@4 319 for(yl = yoffset; yl <= (lastLineYPos); yl+= gridSize){
rt300@4 320
rt300@4 321 ypos = yl/scale;
rt300@4 322 ofLine(xstart, ypos, xfinish, ypos);
rt300@4 323 }
rt300@4 324
rt300@4 325
rt300@4 326 }else if (divsr < 1){
rt300@4 327 // ignore...
rt300@4 328 done = true;
rt300@4 329 }
rt300@4 330
rt300@4 331 power++;
rt300@4 332 }
rt300@4 333 //cout << "draw done" << "\n";
rt300@4 334 //displayInfo();
rt300@4 335
rt300@4 336 drawPresets();
rt300@33 337
rt300@4 338 // draw centre cross hairs
rt300@5 339 drawCrossHairs();
rt300@33 340
rt300@33 341
rt300@33 342 // draw the undo history trail, given viewing area
rt300@33 343 eventLogger.drawTrail(topLeft, topLeft + size);
rt300@33 344
rt300@4 345 ////////-------////////
rt300@4 346 /*
rt300@4 347 ostringstream temp;
rt300@4 348 temp << "Centre x = " << centre.x << "\n y = " << centre.y << " ";
rt300@4 349 string s = temp.str();
rt300@4 350 ofDrawBitmapString( s, pixSize.x/2+10, pixSize.y/2+10 );
rt300@4 351 */
rt300@4 352 }
rt300@5 353 //-----------------------------------------------------------------------
rt300@5 354 void Grid::drawCrossHairs(){
rt300@5 355 // snapping
rt300@5 356 TwoVector pos;
rt300@5 357 if(snapped){
rt300@5 358 pos = coordToPixel(snapCentre);
rt300@5 359 }else{
rt300@5 360 pos = coordToPixel(centre);
rt300@5 361
rt300@5 362 }
rt300@5 363 ofSetColor(255, 0, 0);
rt300@5 364 ofNoFill();
rt300@5 365 ofLine(pos.x-20, pos.y, pos.x+20, pos.y);
rt300@5 366 ofLine(pos.x, pos.y-20, pos.x, pos.y+20);
rt300@5 367 ofEllipse(pos.x, pos.y, 20, 20);
rt300@5 368 ofFill();
rt300@5 369 }
rt300@5 370 //-----------------------------------------------------------------------
rt300@4 371 TwoVector Grid::coordToPixel(TwoVector coord){
rt300@4 372 TwoVector pix;
rt300@4 373 pix.x = (coord.x - topLeft.x)/scale;
rt300@4 374 pix.y = (coord.y - topLeft.y)/scale;
rt300@4 375 return pix;
rt300@4 376
rt300@4 377 }
rt300@4 378
rt300@4 379 //-----------------------------------------------------------------------
rt300@4 380 void Grid::drawPresets(){
rt300@5 381 presetManager.drawPresetsInRange(topLeft, topLeft + size);
rt300@7 382 // draw snapped preset info
rt300@7 383 if(snapped && closestPreset != NULL){
rt300@8 384 ofDrawBitmapString( closestPreset->displayTextDescription(), pixSize.x/2+10, pixSize.y/2+10 );
rt300@7 385 }
rt300@33 386
rt300@4 387 }
rt300@4 388
rt300@4 389 //-----------------------------------------------------------------------
rt300@4 390 void Grid::displayInfo(){
rt300@4 391
rt300@4 392 // display some "useful information"
rt300@4 393
rt300@4 394 ofSetColor(255,255,255,255);
rt300@4 395
rt300@4 396 ostringstream temp;
rt300@4 397 int line = 10; // text output pos
rt300@4 398
rt300@4 399
rt300@4 400 ////////-------/////////
rt300@4 401 temp << "scale = " << scale << " ";
rt300@4 402 string s = temp.str();
rt300@4 403 ofDrawBitmapString( s, 10, line );
rt300@4 404 line+=30;
rt300@4 405 temp.str("");
rt300@4 406 ////////-------/////////
rt300@4 407 temp << "Top Left = " << topLeft.x << "," << topLeft.y << " ";
rt300@4 408 s = temp.str();
rt300@4 409 ofDrawBitmapString( s, 10, line );
rt300@4 410 line+=60;
rt300@4 411 temp.str("");
rt300@4 412
rt300@4 413 ////////-------/////////
rt300@4 414 temp << "View Size = " << size.x << "," << size.y << " ";
rt300@4 415 s = temp.str();
rt300@4 416 ofDrawBitmapString( s, 10, line );
rt300@4 417 line+=60;
rt300@4 418 temp.str("");
rt300@4 419
rt300@4 420 ////////-------/////////
rt300@4 421
rt300@4 422 for(int i=0;i<10;i++){ // TODO 5bit specific
rt300@4 423 temp << midiCC[i] << " ";
rt300@4 424 s = temp.str();
rt300@4 425 ofDrawBitmapString( s, 10, line );
rt300@4 426 line+=20;
rt300@4 427 temp.str("");
rt300@4 428 }
rt300@4 429 }
rt300@4 430 //--------------------------------------------------------------
rt300@4 431 void Grid::update(){ // ?
rt300@4 432 // "update" bit of a crap name - all we do here is calculate the dimension params from the x,y position
rt300@4 433
rt300@4 434
rt300@4 435 }
rt300@5 436
rt300@4 437 //--------------------------------------------------------------
rt300@33 438
rt300@4 439 void Grid::move(TwoVector moveP){
rt300@4 440 // numspacing, pixelspacing stay the same
rt300@4 441
rt300@4 442 // convert pixels to surf units
rt300@4 443 TwoVector moveS;
rt300@4 444 moveS = moveP * scale;
rt300@4 445
rt300@4 446 topLeft = topLeft - moveS; // - because moving to the right means taking away from offset
rt300@4 447 centre = centre - moveS;
rt300@4 448
rt300@4 449 viewWasChanged();
rt300@5 450 eventLogger.logEvent(SCROLL, centre, scale);
rt300@4 451
rt300@4 452 }
rt300@4 453 //--------------------------------------------------------------
rt300@4 454 void Grid::zoom(float factor){
rt300@5 455 if(snapped)centre = (centre + snapCentre)*0.5; // clunky
rt300@5 456
rt300@4 457 if(maxZoom && factor > 1.0){
rt300@4 458 return;
rt300@4 459
rt300@4 460 }
rt300@4 461 if(factor < 1.0){
rt300@4 462 maxZoom = false;
rt300@4 463 }
rt300@4 464 if(minZoom && factor < 1.0){
rt300@4 465 return;
rt300@4 466
rt300@4 467 }
rt300@4 468 if(factor > 1.0){
rt300@4 469 minZoom = false;
rt300@4 470 }
rt300@4 471 scale = scale*factor; // simple eh?
rt300@4 472
rt300@4 473 // update view size using centre
rt300@4 474 // and scale...
rt300@4 475 size.x = size.x*factor; // zooming in, size gets SMALLER (view less)
rt300@4 476 size.y = size.y*factor;
rt300@4 477
rt300@4 478
rt300@4 479
rt300@4 480 viewWasChanged();
rt300@5 481 eventLogger.logEvent(ZOOM, centre, scale);
rt300@4 482
rt300@5 483 }
rt300@5 484 //--------------------------------------------------------------
rt300@20 485 void Grid::shiftCentreToSnapped(){
rt300@20 486 // TODO just in case we're freezing something
rt300@20 487 // snapping actually change centre
rt300@20 488 centre = snapCentre;
rt300@20 489
rt300@20 490 }
rt300@20 491 //--------------------------------------------------------------
rt300@5 492 void Grid::snapCheck(){
rt300@5 493 // check environs for presets.
rt300@7 494
rt300@5 495 vector<Preset *> closePresets = presetManager.getPresetsInRange(centre - snapDist*scale, centre + snapDist*scale);
rt300@5 496 if(closePresets.size() > 0){
rt300@5 497 snapped = true;
rt300@5 498 // find closest
rt300@5 499 double dist, mindist = maxValue;
rt300@5 500 closestPreset = closePresets[0];
rt300@5 501
rt300@5 502 for(vector<Preset *>::iterator piter = closePresets.begin(); piter < closePresets.end(); piter++){
rt300@5 503 dist = (*piter)->coordinates.distanceTo(centre);
rt300@5 504
rt300@5 505 if(dist < mindist){
rt300@5 506 mindist = dist;
rt300@5 507 closestPreset = *piter;
rt300@5 508 }
rt300@5 509 }
rt300@5 510 snapCentre = closestPreset->coordinates;
rt300@22 511 eventLogger.logEvent(SNAPPED_TO_PRESET, getCoord(),closestPreset->creationTime );
rt300@22 512 cout << "SNAPPED CHECK\n";
rt300@5 513 }else{
rt300@5 514 snapped = false;
rt300@7 515 closestPreset = NULL;
rt300@5 516 snapCentre = centre;
rt300@5 517 }
rt300@5 518
rt300@4 519
rt300@4 520 }
rt300@4 521 //--------------------------------------------------------------
rt300@5 522 void Grid::setMaxZoom(){ // got to smallest (white)
rt300@5 523 if(snapped)centre = snapCentre;
rt300@5 524 size.x = maxValue*2.0;
rt300@5 525 scale = size.x/pixSize.x;
rt300@5 526 size.y = scale * pixSize.y;
rt300@7 527 maxZoom = true;
rt300@7 528 minZoom = false;
rt300@5 529 viewWasChanged();
rt300@5 530 }
rt300@5 531 //--------------------------------------------------------------
rt300@5 532 void Grid::setMinZoom(){ // go to entire space (orange)
rt300@5 533 if(snapped)centre = snapCentre;
rt300@5 534 size.x = minValue*2.0;
rt300@5 535 scale = size.x/pixSize.x;
rt300@5 536 size.y = scale * pixSize.y;
rt300@7 537 minZoom = true;
rt300@7 538 maxZoom = false;
rt300@5 539 viewWasChanged();
rt300@4 540 }
rt300@4 541 //--------------------------------------------------------------
rt300@4 542 void Grid::viewWasChanged(){
rt300@5 543 snapCheck();
rt300@4 544 checkLimits();
rt300@5 545 // calculate new params?
rt300@5 546 vector<int> params;
rt300@5 547 if(snapped){
rt300@5 548 params = calculateParamsFromCoord(snapCentre);
rt300@5 549 }else{
rt300@5 550 params = calculateParamsFromCoord(centre);
rt300@5 551 }
rt300@4 552 for(int i = 0;i<2*paramsPerDim;i++){
rt300@4 553 midiCC[i] = params[i];
rt300@4 554 }
rt300@4 555
rt300@4 556 }
rt300@4 557
rt300@4 558 //--------------------------------------------------------------
rt300@4 559 void Grid::checkLimits(){
rt300@4 560 // check for maximum zoom level
rt300@5 561
rt300@4 562
rt300@4 563 if(size.x > maxValue*2.0){
rt300@4 564 cout << "maxZoom\n";
rt300@4 565 maxZoom = true;
rt300@4 566 size.x = maxValue*2.0;
rt300@4 567 // need to also set y size back to
rt300@4 568 }
rt300@4 569 if(size.y > maxValue*2.0){
rt300@4 570 cout << "maxZoom\n";
rt300@4 571 maxZoom = true;
rt300@4 572 size.y = maxValue*2.0;
rt300@4 573 }
rt300@4 574
rt300@4 575 if(size.x < minValue){
rt300@4 576 cout << "min Zoom\n";
rt300@4 577 minZoom = true;
rt300@4 578 size.x = minValue;
rt300@4 579 // need to also set y size back to
rt300@4 580 }
rt300@4 581 if(size.y < minValue){
rt300@4 582 minZoom = true;
rt300@4 583 cout << "min Zoom\n";
rt300@4 584 size.y = minValue;
rt300@4 585 }
rt300@4 586
rt300@4 587 scale = size.x/pixSize.x;
rt300@4 588 size.y = scale * pixSize.y;
rt300@4 589
rt300@4 590 topLeft.x = centre.x - size.x/2;
rt300@4 591 topLeft.y = centre.y - size.y/2;
rt300@4 592 // check for negatives
rt300@4 593
rt300@4 594 // allow centre to be at limits
rt300@4 595 if((topLeft.x + size.x*0.5) < 0.0){
rt300@4 596 cout << "left Wall\n";
rt300@4 597 topLeft.x = 0.0 - size.x*0.5;
rt300@4 598 centre.x = 0.0;
rt300@4 599 }
rt300@4 600
rt300@4 601 if(topLeft.y + size.y*0.5 < 0.0) {
rt300@4 602 cout << "top Wall\n";
rt300@4 603 topLeft.y = 0.0 - size.y*0.5;
rt300@4 604 centre.y = 0.0;
rt300@4 605 }
rt300@4 606
rt300@4 607 // does topleft refer to lines or view?
rt300@4 608
rt300@4 609 // check max
rt300@4 610 if(topLeft.x + size.x/2 > maxValue){
rt300@4 611 cout << "right Wall\n";
rt300@4 612 topLeft.x = maxValue - size.x/2;
rt300@4 613 centre.x = maxValue;
rt300@4 614 }
rt300@4 615 if(topLeft.y + size.y/2 > maxValue) {
rt300@4 616 cout << "bottom Wall\n";
rt300@4 617 topLeft.y = maxValue - size.y/2;
rt300@4 618 centre.y = maxValue;
rt300@4 619 }
rt300@4 620
rt300@4 621 }
rt300@4 622 //--------------------------------------------------------------
rt300@4 623 void Grid::checkConsistencies(){
rt300@4 624 // debug function to check all the parameters are consistent maybe
rt300@4 625
rt300@4 626 }
rt300@4 627 //--------------------------------------------------------------
rt300@4 628 void Grid::setCoord(TwoVector coord){
rt300@4 629
rt300@4 630 centre = coord;
rt300@5 631
rt300@4 632 viewWasChanged();
rt300@4 633 }
rt300@4 634 //--------------------------------------------------------------
rt300@4 635 TwoVector Grid::getCoord(){
rt300@5 636 // return read point crosshairs
rt300@5 637 if(snapped){
rt300@5 638 return snapCentre;
rt300@5 639 }
rt300@4 640 return centre;
rt300@4 641 }
rt300@4 642 //--------------------------------------------------------------
rt300@4 643 vector<int> Grid::getParams(){
rt300@4 644 // return a vector with midiCCs in
rt300@4 645 // should we store params somewhere and use this as a low computation get ?
rt300@4 646 vector<int> params(2*paramsPerDim,0);
rt300@4 647 //
rt300@4 648 for(int i = 0;i<2*paramsPerDim;i++){
rt300@4 649 params[i] = midiCC[i];
rt300@4 650 }
rt300@4 651 return params;
rt300@4 652 }
rt300@4 653 //--------------------------------------------------------------
rt300@4 654 void Grid::setParams(vector<int> params){
rt300@4 655 // input midiCCs, and go to the appropriate coordinate
rt300@4 656
rt300@4 657 for(int i = 0;i<2*paramsPerDim;i++){
rt300@4 658 midiCC[i] = 64;
rt300@4 659 }
rt300@4 660 TwoVector coord = calculateCoordFromParams(params);
rt300@4 661 setCoord(coord);
rt300@4 662
rt300@20 663 // snapping?
rt300@4 664 viewWasChanged();
rt300@4 665
rt300@4 666 }
rt300@4 667 //--------------------------------------------------------------
rt300@5 668 //--------------------------------------------------------------
rt300@5 669 //--------------------------------------------------------------
rt300@5 670 //--------------------------------------------------------------
rt300@5 671 //--------------------------------------------------------------
rt300@5 672 #pragma mark const utils
rt300@5 673
rt300@4 674 TwoVector Grid::calculateCoordFromParams(vector<int> params) const{
rt300@4 675
rt300@4 676 vector<int> ccValueX(paramsPerDim);
rt300@4 677 vector<int> ccValueY(paramsPerDim);
rt300@4 678 for(int i=0;i<paramsPerDim;i++){
rt300@4 679 ccValueX[i] = params[i];
rt300@4 680 ccValueY[i] = params[i+paramsPerDim];
rt300@4 681 }
rt300@4 682 vector<vector <bool> > codesX = midiToGray(ccValueX);
rt300@4 683 vector<vector <bool> > codesY = midiToGray(ccValueY);
rt300@4 684
rt300@4 685 vector<int> base32X = codesToBase32(codesX);
rt300@4 686 vector<int> base32Y = codesToBase32(codesY);
rt300@4 687
rt300@4 688 TwoVector result;
rt300@4 689 result.x = base32toCoord(base32X);
rt300@4 690 result.y = base32toCoord(base32Y);
rt300@4 691 return result;
rt300@4 692 }
rt300@4 693
rt300@4 694 //--------------------------------------------------------------
rt300@4 695 vector<int> Grid::calculateParamsFromCoord(TwoVector coord) const{
rt300@4 696 // some arrays in reverse order of power from normal numbers! 1,2,4,
rt300@4 697
rt300@4 698 // centre to base 32
rt300@4 699 if (coord.x > maxValue || coord.y > maxValue){
rt300@4 700 cout << "calculateParams Error: centre double value is too large" << "\n";
rt300@4 701 vector<int> empty;
rt300@4 702 return empty;
rt300@4 703 }
rt300@4 704
rt300@4 705 //--------------------------
rt300@4 706 // X
rt300@4 707 vector<int> base32x = coordTobase32(coord.x); // 7 numbers from 0 to 31
rt300@4 708 vector<vector <bool> > grayCodesX;
rt300@4 709
rt300@4 710 int size = base32x.size();
rt300@4 711 for(int i=0;i<size;i++){
rt300@4 712 grayCodesX.push_back(intToGray(base32x[i]));
rt300@4 713 }
rt300@4 714
rt300@4 715 vector<int> result;
rt300@4 716 result = grayToMidi(grayCodesX);
rt300@4 717 //--------------------------
rt300@4 718 // AND FOR Y
rt300@4 719 vector<int> base32y = coordTobase32(coord.y);
rt300@4 720 vector<vector <bool> > grayCodesY;
rt300@4 721
rt300@4 722 size = base32y.size();
rt300@4 723 for(int i=0;i<size;i++){
rt300@4 724 grayCodesY.push_back(intToGray(base32y[i]));
rt300@4 725 }
rt300@4 726
rt300@4 727 vector<int> resultY;
rt300@4 728 resultY = grayToMidi(grayCodesY);
rt300@4 729
rt300@4 730 // concatenate
rt300@4 731 result.insert( result.end(), resultY.begin(), resultY.end() );
rt300@4 732 return result;
rt300@4 733 }
rt300@4 734 //-------------------------------------------------------------------
rt300@4 735
rt300@4 736 // for 1 dimension!!! i.e. call this twice
rt300@4 737 vector<int> Grid::grayToMidi(vector<vector <bool> > grayCodes) const{
rt300@4 738
rt300@4 739 // gray to midi CC values
rt300@4 740 // loop thru the scales to build up a CC number per dimension
rt300@4 741 int midiCCresult[paramsPerDim]; // TODO dims specific
rt300@4 742 for(int i=0;i<paramsPerDim;i++){
rt300@4 743 midiCCresult[i] = 0;
rt300@4 744 }
rt300@4 745
rt300@4 746 int bin = 1;
rt300@4 747 bin = bin << grayCodes.size()-1;
rt300@4 748
rt300@4 749 int midP = 0;
rt300@4 750
rt300@4 751 vector<vector <bool> >::iterator piter = grayCodes.begin();
rt300@4 752 for(;piter < grayCodes.end();piter++){ // each lesser power of 2
rt300@4 753 midP = 0; // reset
rt300@4 754 vector<bool>::iterator diter = (*piter).begin();
rt300@4 755 for(; diter <= (*piter).end();diter++){ // each one is different dimension
rt300@4 756 int ig = int(*diter); // convert binary to int
rt300@4 757 //cout << "ig: " << ig;
rt300@4 758 midiCCresult[midP] += ig*bin; // mult by power of two
rt300@4 759 midP++;
rt300@4 760 }
rt300@4 761 bin = bin >> 1; // next power of 2 down
rt300@4 762
rt300@4 763 }
rt300@4 764
rt300@4 765 // put in vector
rt300@4 766 vector<int> result;
rt300@4 767 for(int i=0;i<paramsPerDim;i++){
rt300@4 768 result.push_back(midiCCresult[i]);
rt300@4 769 }
rt300@4 770
rt300@4 771 return result;
rt300@4 772
rt300@4 773
rt300@4 774 }
rt300@4 775
rt300@4 776
rt300@4 777 //--------------------------------------------------------------
rt300@4 778
rt300@4 779 vector<bool> Grid::intToGray(int num, int dimToTravel) const{
rt300@4 780
rt300@4 781 // dimToTravel - this is the dimension that we want the walk to traverse, i.e. the last non zero digit of the code
rt300@4 782 // so swap it for 3 to produce correct orientation
rt300@4 783
rt300@4 784 // just use look up table... until it gets huuuge.
rt300@4 785 vector<bool> grayCode = vcode[num];
rt300@4 786 grayCode[3] = vcode[num][dimToTravel];
rt300@4 787 grayCode[dimToTravel] = vcode[num][3];
rt300@4 788 return grayCode;
rt300@4 789 }
rt300@4 790 //--------------------------------------------------------------
rt300@4 791 vector<int> Grid::walkDiff(vector<bool> left, vector<bool> right){
rt300@4 792 // horrible
rt300@4 793 vector<int> result(2,0);
rt300@4 794
rt300@4 795 int size = left.size();
rt300@4 796 for(int i = 0; i < size; i++){
rt300@4 797 if(left[i] && !right[i]){ // 1 - 0
rt300@4 798 // dim
rt300@4 799 result[0] = i;
rt300@4 800 result[1] = 1;
rt300@4 801 }else if(!left[i] && right[i]){ // 0 - 1
rt300@4 802 result[0] = i;
rt300@4 803 result[1] = -1;
rt300@4 804 }else{ // equal do nothing
rt300@4 805
rt300@4 806
rt300@4 807 }
rt300@4 808 }
rt300@4 809
rt300@4 810 return result;
rt300@4 811 }
rt300@4 812
rt300@4 813 //--------------------------------------------------------------
rt300@4 814 /*
rt300@4 815 breaks down float into a base 32 number (2^D)
rt300@4 816 each of these is converted to gray code
rt300@4 817 this is then converted to 10 parameters, where each 32-digit becomes separate power of 2
rt300@4 818 so "zoom" grid 32-patches are converted to 2-scales. 1,2,4,8,16,32,64,(128?) biggest number is 32^7
rt300@4 819 */
rt300@4 820 vector<int> Grid::coordTobase32(double value) const{
rt300@4 821 //double base = 32.0;
rt300@4 822 if(value < 0.0){
rt300@4 823 cout << "coordTobase32 error: input value is negative\n";
rt300@4 824 value = 0.0;
rt300@4 825 }else if(value > maxValue){
rt300@4 826 cout << "coordTobase32 error: input value too big!\n";
rt300@4 827 }
rt300@4 828 double rem, divdr = 0.0;
rt300@4 829 int digit32;
rt300@4 830
rt300@4 831 // what power of 32 to start at?
rt300@4 832 int maxpow = 7; // midi cc specific
rt300@4 833 vector<int> result;
rt300@4 834
rt300@4 835 rem = value;
rt300@4 836 for(;maxpow >=0;maxpow--){
rt300@4 837 // repeatedly get digit and remainder. This is exactly what we're doing in draw !?... could put all this in one place?
rt300@4 838 divdr = pow((double)codeLength,(double)maxpow);
rt300@4 839 digit32 = floor(rem/divdr);
rt300@4 840 rem = rem - digit32*divdr;
rt300@4 841 result.push_back(digit32); // array, biggest index is smallest power
rt300@4 842 }
rt300@4 843 // at this point rem should be fractional... use for interp?
rt300@4 844
rt300@4 845 return result;
rt300@4 846 }
rt300@4 847 //--------------------------------------------------------------
rt300@4 848
rt300@4 849 vector<int> Grid::codesToBase32(vector<vector<bool> > inCodes) const{
rt300@4 850 vector<int> result;
rt300@4 851 for(int i=0;i<paramBitDepth;i++){
rt300@4 852 result.push_back(grayToInt(inCodes[i]));
rt300@4 853 }
rt300@4 854 return result;
rt300@4 855 }
rt300@4 856 //--------------------------------------------------------------
rt300@4 857
rt300@4 858 int Grid::grayToInt(vector<bool> incode) const{
rt300@4 859 // look for match in table
rt300@4 860
rt300@4 861 int s = vcode.size();
rt300@4 862
rt300@4 863 for(int i=0; i<s;i++){ // fill vector
rt300@4 864 if(vcode[i] == incode){
rt300@4 865 return i;
rt300@4 866 }
rt300@4 867
rt300@4 868 }
rt300@4 869 cout << "grayToInt error: no matching code found!";
rt300@4 870 return -1;
rt300@4 871 }
rt300@4 872 //--------------------------------------------------------------
rt300@4 873 double Grid::base32toCoord(vector<int> base32Digs) const{
rt300@4 874 // build up the big float from a base 32 number
rt300@4 875 double result = 0.0;
rt300@4 876
rt300@4 877 // what power of 32 to start at?
rt300@4 878 int mpow = base32Digs.size() - 1; // should be 7...
rt300@4 879
rt300@4 880 for(int p=0;p<=mpow;p++){ // biggest index is smallest power
rt300@4 881 result += ((double)base32Digs[p]) * pow(32.0, (double)mpow-p);
rt300@4 882
rt300@4 883 }
rt300@4 884 return result;
rt300@4 885
rt300@4 886 }
rt300@4 887 //--------------------------------------------------------------
rt300@4 888 // for 1 dimension - takes in 5 cc params and outputs 7 codes
rt300@4 889 vector<vector <bool> > Grid::midiToGray(vector<int> ccValue) const{
rt300@4 890 int pow2 = 1 << (paramBitDepth-1);
rt300@4 891
rt300@4 892 vector<int> aCode(paramsPerDim);
rt300@4 893 vector<vector<int> > theXCodes(paramBitDepth,aCode);
rt300@4 894
rt300@4 895 // build up binary gray code representations from the bits of the midi ccs
rt300@4 896
rt300@4 897 vector<vector<bool> > theCodes(paramBitDepth, vector<bool>(paramsPerDim));
rt300@4 898
rt300@4 899 // x
rt300@4 900 for(int p=0;p<paramBitDepth;p++){
rt300@4 901
rt300@4 902 for(int i=0;i<paramsPerDim;i++){
rt300@4 903
rt300@4 904 bool bit = (pow2 == (ccValue[i] & pow2));
rt300@4 905 theCodes[p][i] = bit;
rt300@4 906 }
rt300@4 907 pow2 = pow2 >> 1;
rt300@4 908
rt300@4 909 }
rt300@4 910 return theCodes;
rt300@4 911 }
rt300@4 912 //--------------------------------------------------------------
rt300@4 913 //--------------------------------------------------------------
rt300@4 914 //--------------------------------------------------------------