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@37
|
29 interpolateMode = INTERPOLATE_GRID;
|
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@35
|
36 //set scale and position to random
|
rt300@27
|
37 scale = 15500.0;
|
rt300@35
|
38
|
rt300@37
|
39 smallestGridSpacing = 3; //pixels
|
rt300@37
|
40
|
rt300@8
|
41 snapDist = TwoVector(9,9);
|
rt300@5
|
42 snapped = false;
|
rt300@4
|
43
|
rt300@4
|
44 size.setCoord(pixSize.x*scale, pixSize.y*scale);
|
rt300@4
|
45 centre.setCoord(maxValue/2 , maxValue/2);
|
rt300@4
|
46 topLeft.setCoord(centre.x - size.x/2, centre.y - size.y/2);
|
rt300@34
|
47
|
rt300@34
|
48 hilbert.init(paramBitDepth, paramsPerDim);
|
rt300@4
|
49
|
rt300@4
|
50 // set a starting param value, find coord that does it.
|
rt300@4
|
51 vector<int> params(paramsPerDim*2);
|
rt300@4
|
52 for(int i = 0;i<2*paramsPerDim;i++){
|
rt300@4
|
53 midiCC[i] = 12;
|
rt300@4
|
54 params[i] = 12;
|
rt300@4
|
55 }
|
rt300@35
|
56
|
rt300@35
|
57
|
rt300@4
|
58 TwoVector coord = calculateCoordFromParams(params);
|
rt300@4
|
59 setCoord(coord);
|
rt300@4
|
60
|
rt300@4
|
61 viewWasChanged();
|
rt300@37
|
62 calculateInterpolateLevel();
|
rt300@4
|
63 }
|
rt300@4
|
64
|
rt300@4
|
65 template <typename T> int sgn(T val) {
|
rt300@4
|
66 return (T(0) < val) - (val < T(0));
|
rt300@4
|
67 }
|
rt300@37
|
68 //--------------------------------------------------------------
|
rt300@37
|
69 int Grid::calculateInterpolateLevel(){
|
rt300@37
|
70 if(interpolateMode == INTERPOLATE_GRID){
|
rt300@37
|
71 // calculate according to smallest gridlines
|
rt300@37
|
72 // exactly same algorithm as for drawing lines
|
rt300@37
|
73 // i.e. kinda duplicated code.
|
rt300@37
|
74 float markpow = pow(paramsPerDim,2.0);
|
rt300@37
|
75 for(int p = 0; p < paramBitDepth; p++){
|
rt300@37
|
76
|
rt300@37
|
77 double gridSize = pow(markpow,p);
|
rt300@37
|
78 double divsr = size.x / gridSize;
|
rt300@37
|
79
|
rt300@37
|
80 // return the spacing
|
rt300@37
|
81 if( ofGetWidth()/divsr >= smallestGridSpacing){
|
rt300@37
|
82 interpLevel = p;
|
rt300@37
|
83 return p;
|
rt300@37
|
84 }
|
rt300@37
|
85 }
|
rt300@37
|
86 interpLevel = 0;
|
rt300@37
|
87 return 0;
|
rt300@37
|
88 }else{
|
rt300@37
|
89 interpLevel = 0;
|
rt300@37
|
90 return 0; // ???
|
rt300@37
|
91 }
|
rt300@37
|
92 }
|
rt300@37
|
93 //--------------------------------------------------------------
|
rt300@4
|
94
|
rt300@37
|
95 void Grid::draw(){
|
rt300@37
|
96 if(interpolateMode == NO_INTERPOLATION){
|
rt300@37
|
97 drawGridLines();
|
rt300@37
|
98 drawPresets();
|
rt300@37
|
99 }else if(interpolateMode == INTERPOLATE_GRID){
|
rt300@37
|
100 // calculate according to smallest gridlines
|
rt300@37
|
101 drawGridLines();
|
rt300@37
|
102
|
rt300@37
|
103 }else if(interpolateMode == INTERPOLATE_PRESET){
|
rt300@37
|
104 drawPresets();
|
rt300@37
|
105 return; // ???
|
rt300@37
|
106 }
|
rt300@37
|
107
|
rt300@37
|
108
|
rt300@37
|
109
|
rt300@37
|
110 // draw centre cross hairs
|
rt300@37
|
111 drawCrossHairs();
|
rt300@37
|
112
|
rt300@37
|
113
|
rt300@37
|
114 // draw the undo history trail, given viewing area
|
rt300@37
|
115 eventLogger.drawTrail(topLeft, topLeft + size);
|
rt300@37
|
116 }
|
rt300@4
|
117 //--------------------------------------------------------------
|
rt300@37
|
118 void Grid::drawGridLines(){ // draw lines
|
rt300@4
|
119 // TODO too friggin long
|
rt300@4
|
120
|
rt300@16
|
121 pixSize.setCoord(ofGetWidth(), ofGetHeight()); // incase of rotation?
|
rt300@37
|
122
|
rt300@4
|
123 int power = 0;
|
rt300@4
|
124
|
rt300@4
|
125 // these get big!
|
rt300@4
|
126 double divsr;
|
rt300@4
|
127 double yl,xl;
|
rt300@4
|
128 double gridSize = 0;
|
rt300@4
|
129
|
rt300@4
|
130 double firstLineXPos, lastLineXPos,firstLineYPos, lastLineYPos, remleft, xoffset, yoffset = 0.0;
|
rt300@4
|
131 double xstart, xfinish, ystart,yfinish;
|
rt300@4
|
132 // these don't
|
rt300@4
|
133 int xpos, ypos = 0;
|
rt300@4
|
134
|
rt300@4
|
135 float alpha;
|
rt300@4
|
136 bool done = false;
|
rt300@37
|
137 float markpow = 1 << paramsPerDim; // power that denotes next grid markings e.g. 32
|
rt300@4
|
138 int lineWidth = 0;
|
rt300@4
|
139 int colCycle = 0;
|
rt300@4
|
140
|
rt300@4
|
141
|
rt300@37
|
142 // loop thru powers of (base?) smallest to biggest
|
rt300@37
|
143 // to determine which should be shown as grids
|
rt300@4
|
144 while (!done){
|
rt300@4
|
145 gridSize = pow(markpow,power);
|
rt300@4
|
146
|
rt300@37
|
147 colCycle = power % paramBitDepth;
|
rt300@4
|
148
|
rt300@4
|
149 divsr = size.x / gridSize;
|
rt300@4
|
150
|
rt300@4
|
151 // if (divisor i.e. number of lines is less than 1000
|
rt300@37
|
152 if( ofGetWidth()/divsr >= smallestGridSpacing){
|
rt300@4
|
153
|
rt300@4
|
154 // calculate transparency
|
rt300@37
|
155 float visCont = log10(divsr*2); // 0 if only 1 line, 3 if 1000 lines
|
rt300@4
|
156 alpha = 90*(3 - visCont);
|
rt300@4
|
157 ofSetLineWidth(lineWidth);
|
rt300@4
|
158
|
rt300@4
|
159 // cycle colors for different scales
|
rt300@4
|
160 if(colCycle == 0){
|
rt300@4
|
161 ofSetColor(255,255,255,alpha);
|
rt300@4
|
162 }else if(colCycle == 1){
|
rt300@4
|
163 ofSetColor(255,0,0,alpha);
|
rt300@4
|
164 }else if(colCycle == 2){
|
rt300@4
|
165 ofSetColor(0,0,255,alpha);
|
rt300@4
|
166 }else if(colCycle == 3){
|
rt300@4
|
167 ofSetColor(0,255,0,alpha);
|
rt300@4
|
168 }else if(colCycle == 4){
|
rt300@4
|
169 ofSetColor(255,0,255,alpha);
|
rt300@4
|
170 }else if(colCycle == 5){
|
rt300@4
|
171 ofSetColor(0,255,255,alpha);
|
rt300@4
|
172 }else if(colCycle == 6){
|
rt300@4
|
173 ofSetColor(255,255,0,alpha);
|
rt300@4
|
174 }else if(colCycle == 7){
|
rt300@4
|
175 ofSetColor(255,255,255,alpha);
|
rt300@4
|
176 }else{
|
rt300@4
|
177 cout << "err colour messed up\n";
|
rt300@4
|
178 }
|
rt300@4
|
179
|
rt300@4
|
180
|
rt300@4
|
181 // draw level numbers associated with each color. This would not be true if markpow wasnt 2^d
|
rt300@4
|
182 ////////-------/////////
|
rt300@4
|
183 /*
|
rt300@4
|
184 temp << "THIS LEVEL = " << (int)pow(2.0,power) << " ";
|
rt300@4
|
185 string s = temp.str();
|
rt300@4
|
186 ofDrawBitmapString( s, 10, line );
|
rt300@4
|
187 line+=30;
|
rt300@4
|
188 temp.str("");
|
rt300@4
|
189 *////////-------/////////
|
rt300@4
|
190
|
rt300@4
|
191 // draw presets at this level
|
rt300@4
|
192 // fill in smallest squares if they contain a preset
|
rt300@4
|
193 // how to do this efficiently?
|
rt300@4
|
194
|
rt300@4
|
195
|
rt300@4
|
196 if(topLeft.x < 0.0){
|
rt300@4
|
197 firstLineXPos = 0.0;
|
rt300@4
|
198 xoffset = firstLineXPos - topLeft.x;
|
rt300@4
|
199 xstart = xoffset/scale;
|
rt300@4
|
200 }else{
|
rt300@4
|
201 firstLineXPos = topLeft.x;
|
rt300@4
|
202 // kinda float version of % operator
|
rt300@4
|
203 remleft = ceil(firstLineXPos/gridSize);
|
rt300@4
|
204 xoffset = (remleft * gridSize) - topLeft.x;
|
rt300@4
|
205 xstart = 0;
|
rt300@4
|
206 }
|
rt300@4
|
207 if(topLeft.x + size.x > maxValue){
|
rt300@4
|
208 lastLineXPos = maxValue+1 - topLeft.x;
|
rt300@4
|
209
|
rt300@4
|
210
|
rt300@4
|
211 }else{
|
rt300@4
|
212 lastLineXPos = size.x;
|
rt300@4
|
213
|
rt300@4
|
214 }
|
rt300@4
|
215 xfinish = lastLineXPos/scale;
|
rt300@4
|
216
|
rt300@4
|
217 //////////------------------------
|
rt300@4
|
218 // same for y
|
rt300@4
|
219
|
rt300@4
|
220 if(topLeft.y < 0.0){
|
rt300@4
|
221 firstLineYPos = 0.0;
|
rt300@4
|
222 yoffset = firstLineYPos - topLeft.y;
|
rt300@4
|
223 ystart = yoffset/scale;
|
rt300@4
|
224 }else{
|
rt300@4
|
225 firstLineYPos = topLeft.y;
|
rt300@4
|
226 // kinda float version of % operator
|
rt300@4
|
227 remleft = ceil(firstLineYPos/gridSize);
|
rt300@4
|
228 yoffset = (remleft * gridSize) - topLeft.y;
|
rt300@4
|
229 ystart = 0;
|
rt300@4
|
230 }
|
rt300@4
|
231 if(topLeft.y + size.y > maxValue){
|
rt300@4
|
232 lastLineYPos = maxValue+1 - topLeft.y;
|
rt300@4
|
233
|
rt300@4
|
234 }else{
|
rt300@4
|
235 lastLineYPos = size.y;
|
rt300@4
|
236
|
rt300@4
|
237 }
|
rt300@4
|
238 yfinish = lastLineYPos/scale;
|
rt300@4
|
239 // -------------------------------------------
|
rt300@4
|
240 // now draw
|
rt300@4
|
241 for(xl = xoffset; xl <= (lastLineXPos); xl+= gridSize){
|
rt300@4
|
242
|
rt300@4
|
243 xpos = xl/scale;
|
rt300@4
|
244 ofLine(xpos, ystart, xpos, yfinish);
|
rt300@4
|
245
|
rt300@4
|
246 }
|
rt300@4
|
247
|
rt300@4
|
248 for(yl = yoffset; yl <= (lastLineYPos); yl+= gridSize){
|
rt300@4
|
249
|
rt300@4
|
250 ypos = yl/scale;
|
rt300@4
|
251 ofLine(xstart, ypos, xfinish, ypos);
|
rt300@4
|
252 }
|
rt300@4
|
253
|
rt300@4
|
254
|
rt300@37
|
255 }
|
rt300@37
|
256 /*else if (divsr < 1){
|
rt300@37
|
257 // maximum only one line. worth checking so that bigger lines still show up?
|
rt300@4
|
258 done = true;
|
rt300@4
|
259 }
|
rt300@37
|
260 */
|
rt300@4
|
261 power++;
|
rt300@37
|
262 if(power > paramBitDepth)
|
rt300@37
|
263 done = true;
|
rt300@37
|
264
|
rt300@4
|
265 }
|
rt300@4
|
266 //cout << "draw done" << "\n";
|
rt300@4
|
267 //displayInfo();
|
rt300@4
|
268
|
rt300@33
|
269
|
rt300@33
|
270
|
rt300@4
|
271 ////////-------////////
|
rt300@4
|
272 /*
|
rt300@4
|
273 ostringstream temp;
|
rt300@4
|
274 temp << "Centre x = " << centre.x << "\n y = " << centre.y << " ";
|
rt300@4
|
275 string s = temp.str();
|
rt300@4
|
276 ofDrawBitmapString( s, pixSize.x/2+10, pixSize.y/2+10 );
|
rt300@4
|
277 */
|
rt300@4
|
278 }
|
rt300@5
|
279 //-----------------------------------------------------------------------
|
rt300@5
|
280 void Grid::drawCrossHairs(){
|
rt300@5
|
281 // snapping
|
rt300@5
|
282 TwoVector pos;
|
rt300@5
|
283 if(snapped){
|
rt300@5
|
284 pos = coordToPixel(snapCentre);
|
rt300@5
|
285 }else{
|
rt300@5
|
286 pos = coordToPixel(centre);
|
rt300@5
|
287
|
rt300@5
|
288 }
|
rt300@5
|
289 ofSetColor(255, 0, 0);
|
rt300@5
|
290 ofNoFill();
|
rt300@5
|
291 ofLine(pos.x-20, pos.y, pos.x+20, pos.y);
|
rt300@5
|
292 ofLine(pos.x, pos.y-20, pos.x, pos.y+20);
|
rt300@5
|
293 ofEllipse(pos.x, pos.y, 20, 20);
|
rt300@5
|
294 ofFill();
|
rt300@5
|
295 }
|
rt300@5
|
296 //-----------------------------------------------------------------------
|
rt300@4
|
297 TwoVector Grid::coordToPixel(TwoVector coord){
|
rt300@4
|
298 TwoVector pix;
|
rt300@4
|
299 pix.x = (coord.x - topLeft.x)/scale;
|
rt300@4
|
300 pix.y = (coord.y - topLeft.y)/scale;
|
rt300@4
|
301 return pix;
|
rt300@4
|
302
|
rt300@4
|
303 }
|
rt300@4
|
304
|
rt300@4
|
305 //-----------------------------------------------------------------------
|
rt300@4
|
306 void Grid::drawPresets(){
|
rt300@5
|
307 presetManager.drawPresetsInRange(topLeft, topLeft + size);
|
rt300@7
|
308 // draw snapped preset info
|
rt300@7
|
309 if(snapped && closestPreset != NULL){
|
rt300@8
|
310 ofDrawBitmapString( closestPreset->displayTextDescription(), pixSize.x/2+10, pixSize.y/2+10 );
|
rt300@7
|
311 }
|
rt300@33
|
312
|
rt300@4
|
313 }
|
rt300@4
|
314
|
rt300@4
|
315 //-----------------------------------------------------------------------
|
rt300@4
|
316 void Grid::displayInfo(){
|
rt300@4
|
317
|
rt300@4
|
318 // display some "useful information"
|
rt300@4
|
319
|
rt300@4
|
320 ofSetColor(255,255,255,255);
|
rt300@4
|
321
|
rt300@4
|
322 ostringstream temp;
|
rt300@4
|
323 int line = 10; // text output pos
|
rt300@4
|
324
|
rt300@4
|
325
|
rt300@4
|
326 ////////-------/////////
|
rt300@4
|
327 temp << "scale = " << scale << " ";
|
rt300@4
|
328 string s = temp.str();
|
rt300@4
|
329 ofDrawBitmapString( s, 10, line );
|
rt300@4
|
330 line+=30;
|
rt300@4
|
331 temp.str("");
|
rt300@4
|
332 ////////-------/////////
|
rt300@4
|
333 temp << "Top Left = " << topLeft.x << "," << topLeft.y << " ";
|
rt300@4
|
334 s = temp.str();
|
rt300@4
|
335 ofDrawBitmapString( s, 10, line );
|
rt300@4
|
336 line+=60;
|
rt300@4
|
337 temp.str("");
|
rt300@4
|
338
|
rt300@4
|
339 ////////-------/////////
|
rt300@4
|
340 temp << "View Size = " << size.x << "," << size.y << " ";
|
rt300@4
|
341 s = temp.str();
|
rt300@4
|
342 ofDrawBitmapString( s, 10, line );
|
rt300@4
|
343 line+=60;
|
rt300@4
|
344 temp.str("");
|
rt300@4
|
345
|
rt300@4
|
346 ////////-------/////////
|
rt300@4
|
347
|
rt300@4
|
348 for(int i=0;i<10;i++){ // TODO 5bit specific
|
rt300@4
|
349 temp << midiCC[i] << " ";
|
rt300@4
|
350 s = temp.str();
|
rt300@4
|
351 ofDrawBitmapString( s, 10, line );
|
rt300@4
|
352 line+=20;
|
rt300@4
|
353 temp.str("");
|
rt300@4
|
354 }
|
rt300@4
|
355 }
|
rt300@4
|
356 //--------------------------------------------------------------
|
rt300@4
|
357 void Grid::update(){ // ?
|
rt300@4
|
358
|
rt300@4
|
359
|
rt300@4
|
360 }
|
rt300@5
|
361
|
rt300@4
|
362 //--------------------------------------------------------------
|
rt300@33
|
363
|
rt300@4
|
364 void Grid::move(TwoVector moveP){
|
rt300@4
|
365 // numspacing, pixelspacing stay the same
|
rt300@4
|
366
|
rt300@4
|
367 // convert pixels to surf units
|
rt300@4
|
368 TwoVector moveS;
|
rt300@4
|
369 moveS = moveP * scale;
|
rt300@4
|
370
|
rt300@4
|
371 topLeft = topLeft - moveS; // - because moving to the right means taking away from offset
|
rt300@4
|
372 centre = centre - moveS;
|
rt300@4
|
373
|
rt300@4
|
374 viewWasChanged();
|
rt300@5
|
375 eventLogger.logEvent(SCROLL, centre, scale);
|
rt300@4
|
376
|
rt300@4
|
377 }
|
rt300@4
|
378 //--------------------------------------------------------------
|
rt300@4
|
379 void Grid::zoom(float factor){
|
rt300@5
|
380 if(snapped)centre = (centre + snapCentre)*0.5; // clunky
|
rt300@5
|
381
|
rt300@4
|
382 if(maxZoom && factor > 1.0){
|
rt300@4
|
383 return;
|
rt300@4
|
384
|
rt300@4
|
385 }
|
rt300@4
|
386 if(factor < 1.0){
|
rt300@4
|
387 maxZoom = false;
|
rt300@4
|
388 }
|
rt300@4
|
389 if(minZoom && factor < 1.0){
|
rt300@4
|
390 return;
|
rt300@4
|
391
|
rt300@4
|
392 }
|
rt300@4
|
393 if(factor > 1.0){
|
rt300@4
|
394 minZoom = false;
|
rt300@4
|
395 }
|
rt300@4
|
396 scale = scale*factor; // simple eh?
|
rt300@4
|
397
|
rt300@4
|
398 // update view size using centre
|
rt300@4
|
399 // and scale...
|
rt300@4
|
400 size.x = size.x*factor; // zooming in, size gets SMALLER (view less)
|
rt300@4
|
401 size.y = size.y*factor;
|
rt300@4
|
402
|
rt300@4
|
403
|
rt300@4
|
404
|
rt300@4
|
405 viewWasChanged();
|
rt300@37
|
406 calculateInterpolateLevel();
|
rt300@5
|
407 eventLogger.logEvent(ZOOM, centre, scale);
|
rt300@4
|
408
|
rt300@5
|
409 }
|
rt300@5
|
410 //--------------------------------------------------------------
|
rt300@20
|
411 void Grid::shiftCentreToSnapped(){
|
rt300@20
|
412 // TODO just in case we're freezing something
|
rt300@20
|
413 // snapping actually change centre
|
rt300@20
|
414 centre = snapCentre;
|
rt300@20
|
415
|
rt300@20
|
416 }
|
rt300@20
|
417 //--------------------------------------------------------------
|
rt300@5
|
418 void Grid::snapCheck(){
|
rt300@5
|
419 // check environs for presets.
|
rt300@7
|
420
|
rt300@5
|
421 vector<Preset *> closePresets = presetManager.getPresetsInRange(centre - snapDist*scale, centre + snapDist*scale);
|
rt300@5
|
422 if(closePresets.size() > 0){
|
rt300@5
|
423 snapped = true;
|
rt300@5
|
424 // find closest
|
rt300@5
|
425 double dist, mindist = maxValue;
|
rt300@5
|
426 closestPreset = closePresets[0];
|
rt300@5
|
427
|
rt300@5
|
428 for(vector<Preset *>::iterator piter = closePresets.begin(); piter < closePresets.end(); piter++){
|
rt300@5
|
429 dist = (*piter)->coordinates.distanceTo(centre);
|
rt300@5
|
430
|
rt300@5
|
431 if(dist < mindist){
|
rt300@5
|
432 mindist = dist;
|
rt300@5
|
433 closestPreset = *piter;
|
rt300@5
|
434 }
|
rt300@5
|
435 }
|
rt300@5
|
436 snapCentre = closestPreset->coordinates;
|
rt300@22
|
437 eventLogger.logEvent(SNAPPED_TO_PRESET, getCoord(),closestPreset->creationTime );
|
rt300@35
|
438 //cout << "SNAPPED CHECK\n";
|
rt300@5
|
439 }else{
|
rt300@5
|
440 snapped = false;
|
rt300@7
|
441 closestPreset = NULL;
|
rt300@5
|
442 snapCentre = centre;
|
rt300@5
|
443 }
|
rt300@5
|
444
|
rt300@4
|
445
|
rt300@4
|
446 }
|
rt300@4
|
447 //--------------------------------------------------------------
|
rt300@5
|
448 void Grid::setMaxZoom(){ // got to smallest (white)
|
rt300@5
|
449 if(snapped)centre = snapCentre;
|
rt300@5
|
450 size.x = maxValue*2.0;
|
rt300@5
|
451 scale = size.x/pixSize.x;
|
rt300@5
|
452 size.y = scale * pixSize.y;
|
rt300@7
|
453 maxZoom = true;
|
rt300@7
|
454 minZoom = false;
|
rt300@5
|
455 viewWasChanged();
|
rt300@5
|
456 }
|
rt300@5
|
457 //--------------------------------------------------------------
|
rt300@5
|
458 void Grid::setMinZoom(){ // go to entire space (orange)
|
rt300@5
|
459 if(snapped)centre = snapCentre;
|
rt300@5
|
460 size.x = minValue*2.0;
|
rt300@5
|
461 scale = size.x/pixSize.x;
|
rt300@5
|
462 size.y = scale * pixSize.y;
|
rt300@7
|
463 minZoom = true;
|
rt300@7
|
464 maxZoom = false;
|
rt300@5
|
465 viewWasChanged();
|
rt300@4
|
466 }
|
rt300@4
|
467 //--------------------------------------------------------------
|
rt300@4
|
468 void Grid::viewWasChanged(){
|
rt300@5
|
469 snapCheck();
|
rt300@4
|
470 checkLimits();
|
rt300@5
|
471 // calculate new params?
|
rt300@5
|
472 vector<int> params;
|
rt300@5
|
473 if(snapped){
|
rt300@5
|
474 params = calculateParamsFromCoord(snapCentre);
|
rt300@5
|
475 }else{
|
rt300@37
|
476 if(interpolateMode == NO_INTERPOLATION){
|
rt300@37
|
477 params = calculateParamsFromCoord(centre);
|
rt300@37
|
478 }else if(interpolateMode == INTERPOLATE_GRID){
|
rt300@37
|
479 params = calculateInterpolatedParamsFromCoord(centre);
|
rt300@37
|
480 }
|
rt300@5
|
481 }
|
rt300@4
|
482 for(int i = 0;i<2*paramsPerDim;i++){
|
rt300@4
|
483 midiCC[i] = params[i];
|
rt300@4
|
484 }
|
rt300@4
|
485
|
rt300@4
|
486 }
|
rt300@4
|
487
|
rt300@4
|
488 //--------------------------------------------------------------
|
rt300@4
|
489 void Grid::checkLimits(){
|
rt300@4
|
490 // check for maximum zoom level
|
rt300@5
|
491
|
rt300@4
|
492
|
rt300@4
|
493 if(size.x > maxValue*2.0){
|
rt300@4
|
494 cout << "maxZoom\n";
|
rt300@4
|
495 maxZoom = true;
|
rt300@4
|
496 size.x = maxValue*2.0;
|
rt300@4
|
497 // need to also set y size back to
|
rt300@4
|
498 }
|
rt300@4
|
499 if(size.y > maxValue*2.0){
|
rt300@4
|
500 cout << "maxZoom\n";
|
rt300@4
|
501 maxZoom = true;
|
rt300@4
|
502 size.y = maxValue*2.0;
|
rt300@4
|
503 }
|
rt300@4
|
504
|
rt300@4
|
505 if(size.x < minValue){
|
rt300@4
|
506 cout << "min Zoom\n";
|
rt300@4
|
507 minZoom = true;
|
rt300@4
|
508 size.x = minValue;
|
rt300@4
|
509 // need to also set y size back to
|
rt300@4
|
510 }
|
rt300@4
|
511 if(size.y < minValue){
|
rt300@4
|
512 minZoom = true;
|
rt300@4
|
513 cout << "min Zoom\n";
|
rt300@4
|
514 size.y = minValue;
|
rt300@4
|
515 }
|
rt300@4
|
516
|
rt300@4
|
517 scale = size.x/pixSize.x;
|
rt300@4
|
518 size.y = scale * pixSize.y;
|
rt300@4
|
519
|
rt300@4
|
520 topLeft.x = centre.x - size.x/2;
|
rt300@4
|
521 topLeft.y = centre.y - size.y/2;
|
rt300@4
|
522 // check for negatives
|
rt300@4
|
523
|
rt300@4
|
524 // allow centre to be at limits
|
rt300@4
|
525 if((topLeft.x + size.x*0.5) < 0.0){
|
rt300@4
|
526 cout << "left Wall\n";
|
rt300@4
|
527 topLeft.x = 0.0 - size.x*0.5;
|
rt300@4
|
528 centre.x = 0.0;
|
rt300@4
|
529 }
|
rt300@4
|
530
|
rt300@4
|
531 if(topLeft.y + size.y*0.5 < 0.0) {
|
rt300@4
|
532 cout << "top Wall\n";
|
rt300@4
|
533 topLeft.y = 0.0 - size.y*0.5;
|
rt300@4
|
534 centre.y = 0.0;
|
rt300@4
|
535 }
|
rt300@4
|
536
|
rt300@4
|
537 // does topleft refer to lines or view?
|
rt300@4
|
538
|
rt300@4
|
539 // check max
|
rt300@4
|
540 if(topLeft.x + size.x/2 > maxValue){
|
rt300@4
|
541 cout << "right Wall\n";
|
rt300@4
|
542 topLeft.x = maxValue - size.x/2;
|
rt300@4
|
543 centre.x = maxValue;
|
rt300@4
|
544 }
|
rt300@4
|
545 if(topLeft.y + size.y/2 > maxValue) {
|
rt300@4
|
546 cout << "bottom Wall\n";
|
rt300@4
|
547 topLeft.y = maxValue - size.y/2;
|
rt300@4
|
548 centre.y = maxValue;
|
rt300@4
|
549 }
|
rt300@4
|
550
|
rt300@4
|
551 }
|
rt300@4
|
552 //--------------------------------------------------------------
|
rt300@4
|
553 void Grid::checkConsistencies(){
|
rt300@4
|
554 // debug function to check all the parameters are consistent maybe
|
rt300@4
|
555
|
rt300@4
|
556 }
|
rt300@4
|
557 //--------------------------------------------------------------
|
rt300@4
|
558 void Grid::setCoord(TwoVector coord){
|
rt300@4
|
559
|
rt300@4
|
560 centre = coord;
|
rt300@5
|
561
|
rt300@4
|
562 viewWasChanged();
|
rt300@4
|
563 }
|
rt300@4
|
564 //--------------------------------------------------------------
|
rt300@4
|
565 TwoVector Grid::getCoord(){
|
rt300@5
|
566 // return read point crosshairs
|
rt300@5
|
567 if(snapped){
|
rt300@5
|
568 return snapCentre;
|
rt300@5
|
569 }
|
rt300@4
|
570 return centre;
|
rt300@4
|
571 }
|
rt300@4
|
572 //--------------------------------------------------------------
|
rt300@4
|
573 vector<int> Grid::getParams(){
|
rt300@4
|
574 // return a vector with midiCCs in
|
rt300@4
|
575 // should we store params somewhere and use this as a low computation get ?
|
rt300@4
|
576 vector<int> params(2*paramsPerDim,0);
|
rt300@4
|
577 //
|
rt300@4
|
578 for(int i = 0;i<2*paramsPerDim;i++){
|
rt300@4
|
579 params[i] = midiCC[i];
|
rt300@4
|
580 }
|
rt300@4
|
581 return params;
|
rt300@4
|
582 }
|
rt300@4
|
583 //--------------------------------------------------------------
|
rt300@4
|
584 void Grid::setParams(vector<int> params){
|
rt300@4
|
585 // input midiCCs, and go to the appropriate coordinate
|
rt300@4
|
586
|
rt300@4
|
587 for(int i = 0;i<2*paramsPerDim;i++){
|
rt300@4
|
588 midiCC[i] = 64;
|
rt300@4
|
589 }
|
rt300@4
|
590 TwoVector coord = calculateCoordFromParams(params);
|
rt300@4
|
591 setCoord(coord);
|
rt300@4
|
592
|
rt300@20
|
593 // snapping?
|
rt300@4
|
594 viewWasChanged();
|
rt300@4
|
595
|
rt300@4
|
596 }
|
rt300@4
|
597 //--------------------------------------------------------------
|
rt300@5
|
598 //--------------------------------------------------------------
|
rt300@5
|
599 //--------------------------------------------------------------
|
rt300@5
|
600 //--------------------------------------------------------------
|
rt300@5
|
601 //--------------------------------------------------------------
|
rt300@5
|
602 #pragma mark const utils
|
rt300@5
|
603
|
rt300@37
|
604 TwoVector Grid::calculateCoordFromParams(vector<int> params){
|
rt300@4
|
605
|
rt300@4
|
606 vector<int> ccValueX(paramsPerDim);
|
rt300@4
|
607 vector<int> ccValueY(paramsPerDim);
|
rt300@4
|
608 for(int i=0;i<paramsPerDim;i++){
|
rt300@4
|
609 ccValueX[i] = params[i];
|
rt300@4
|
610 ccValueY[i] = params[i+paramsPerDim];
|
rt300@4
|
611 }
|
rt300@4
|
612
|
rt300@4
|
613 TwoVector result;
|
rt300@35
|
614 result.x = hilbert.calculateIndexFromParams(ccValueX);
|
rt300@35
|
615 result.y = hilbert.calculateIndexFromParams(ccValueY);
|
rt300@4
|
616 return result;
|
rt300@4
|
617 }
|
rt300@4
|
618
|
rt300@4
|
619 //--------------------------------------------------------------
|
rt300@37
|
620 vector<int> Grid::calculateParamsFromCoord(TwoVector coord){
|
rt300@35
|
621
|
rt300@4
|
622 if (coord.x > maxValue || coord.y > maxValue){
|
rt300@4
|
623 cout << "calculateParams Error: centre double value is too large" << "\n";
|
rt300@4
|
624 vector<int> empty;
|
rt300@4
|
625 return empty;
|
rt300@4
|
626 }
|
rt300@35
|
627 if (coord.x < 0 || coord.y < 0){
|
rt300@35
|
628 cout << "calculateParams Error: centre double value is negative" << "\n";
|
rt300@35
|
629 vector<int> empty;
|
rt300@35
|
630 return empty;
|
rt300@4
|
631 }
|
rt300@4
|
632
|
rt300@35
|
633 // X
|
rt300@35
|
634 vector<int> resultX;
|
rt300@35
|
635 resultX = hilbert.calculateParamsFromIndex(coord.x);
|
rt300@35
|
636 // Y
|
rt300@4
|
637 vector<int> resultY;
|
rt300@35
|
638 resultY = hilbert.calculateParamsFromIndex(coord.y);
|
rt300@4
|
639
|
rt300@4
|
640 // concatenate
|
rt300@35
|
641 vector<int> result = resultX;
|
rt300@35
|
642
|
rt300@4
|
643 result.insert( result.end(), resultY.begin(), resultY.end() );
|
rt300@4
|
644 return result;
|
rt300@4
|
645 }
|
rt300@37
|
646 //--------------------------------------------------------------
|
rt300@37
|
647 vector<int> Grid::calculateInterpolatedParamsFromCoord(TwoVector coord){
|
rt300@4
|
648
|
rt300@37
|
649 vector<int> result;
|
rt300@37
|
650 // round by masking according to interpLevel
|
rt300@37
|
651
|
rt300@37
|
652 long long x = coord.x;
|
rt300@37
|
653 long long y = coord.y;
|
rt300@37
|
654 cout << interpLevel << "\n";
|
rt300@37
|
655 int roundDigits = (paramsPerDim*interpLevel);
|
rt300@37
|
656 // knock off last digits
|
rt300@37
|
657 x = x >> roundDigits;
|
rt300@37
|
658 x = x << roundDigits;
|
rt300@37
|
659 float frac = (coord.x - x)/(1 << roundDigits);
|
rt300@37
|
660 long long xlower = x;
|
rt300@37
|
661 long long xupper = x + (1 << roundDigits);
|
rt300@37
|
662
|
rt300@37
|
663 vector<int> pupper = hilbert.calculateParamsFromIndex(xupper);
|
rt300@37
|
664 vector<int> plower = hilbert.calculateParamsFromIndex(xlower);
|
rt300@37
|
665
|
rt300@37
|
666 result = interpVector(pupper,plower,frac);
|
rt300@37
|
667 // now Y
|
rt300@37
|
668 y = y >> roundDigits;
|
rt300@37
|
669 y = y << roundDigits;
|
rt300@37
|
670 frac = (coord.y - y)/(1 << roundDigits);
|
rt300@37
|
671 long long ylower = y;
|
rt300@37
|
672 long long yupper = y + (1 << roundDigits);
|
rt300@37
|
673
|
rt300@37
|
674 pupper = hilbert.calculateParamsFromIndex(yupper);
|
rt300@37
|
675 plower = hilbert.calculateParamsFromIndex(ylower);
|
rt300@37
|
676
|
rt300@37
|
677 vector<int> resultY = interpVector(pupper,plower,frac);
|
rt300@37
|
678 // stickem together
|
rt300@37
|
679 result.insert( result.end(), resultY.begin(), resultY.end() );
|
rt300@37
|
680 return result;
|
rt300@37
|
681 }
|
rt300@37
|
682 //--------------------------------------------------------------
|
rt300@37
|
683 vector<int> Grid::interpVector(vector<int> upper, vector<int> lower, float frac){
|
rt300@37
|
684 vector<int> result;
|
rt300@37
|
685 if(upper.size() != lower.size()){
|
rt300@37
|
686 cout << "Error: interpVector takes vectors of same length" << "\n";
|
rt300@37
|
687 return result;
|
rt300@37
|
688 }
|
rt300@37
|
689 if(frac > 1){
|
rt300@37
|
690 cout << "Error: bad fraction for vector interpolation" << "\n";
|
rt300@37
|
691 return result;
|
rt300@37
|
692 }
|
rt300@37
|
693 int N = upper.size();
|
rt300@37
|
694 for(int i=0; i<N; i++){
|
rt300@37
|
695 result.push_back(frac*upper[i] + (1-frac)*lower[i]);
|
rt300@37
|
696 }
|
rt300@37
|
697 return result;
|
rt300@37
|
698 }
|
rt300@4
|
699 //--------------------------------------------------------------
|
rt300@4
|
700 vector<int> Grid::walkDiff(vector<bool> left, vector<bool> right){
|
rt300@4
|
701 // horrible
|
rt300@4
|
702 vector<int> result(2,0);
|
rt300@4
|
703
|
rt300@4
|
704 int size = left.size();
|
rt300@4
|
705 for(int i = 0; i < size; i++){
|
rt300@4
|
706 if(left[i] && !right[i]){ // 1 - 0
|
rt300@4
|
707 // dim
|
rt300@4
|
708 result[0] = i;
|
rt300@4
|
709 result[1] = 1;
|
rt300@4
|
710 }else if(!left[i] && right[i]){ // 0 - 1
|
rt300@4
|
711 result[0] = i;
|
rt300@4
|
712 result[1] = -1;
|
rt300@4
|
713 }else{ // equal do nothing
|
rt300@4
|
714
|
rt300@4
|
715
|
rt300@4
|
716 }
|
rt300@4
|
717 }
|
rt300@4
|
718
|
rt300@4
|
719 return result;
|
rt300@4
|
720 }
|
rt300@4
|
721 //--------------------------------------------------------------
|
rt300@4
|
722 //--------------------------------------------------------------
|
rt300@4
|
723 //-------------------------------------------------------------- |