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