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