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