Mercurial > hg > soniczoomios
diff grid.mm @ 37:8ed7522deaaa
Interpolation.
author | Robert Tubb <rt300@eecs.qmul.ac.uk> |
---|---|
date | Tue, 09 Apr 2013 17:14:31 +0100 |
parents | 790939017078 |
children | 0dfe9e0c01aa |
line wrap: on
line diff
--- a/grid.mm Tue Apr 09 13:22:28 2013 +0100 +++ b/grid.mm Tue Apr 09 17:14:31 2013 +0100 @@ -4,7 +4,7 @@ // // Created by Robert Tubb on 03/10/2012. // -// +// This is the grid view, i.e. the viewable representation of hilbert surface #include "grid.h" @@ -17,6 +17,7 @@ //-------------------------------------------------------------- Grid::Grid(): maxValue(pow(32.0,7.0)-1), minValue(30), paramsPerDim(5), paramBitDepth(7){ + interpLevel = 4; } //-------------------------------------------------------------- //-------------------------------------------------------------- @@ -25,6 +26,8 @@ } void Grid::init(){ + interpolateMode = INTERPOLATE_GRID; + maxZoom = false; minZoom = false; @@ -33,6 +36,8 @@ //set scale and position to random scale = 15500.0; + smallestGridSpacing = 3; //pixels + snapDist = TwoVector(9,9); snapped = false; @@ -54,20 +59,67 @@ setCoord(coord); viewWasChanged(); - + calculateInterpolateLevel(); } template <typename T> int sgn(T val) { return (T(0) < val) - (val < T(0)); } +//-------------------------------------------------------------- +int Grid::calculateInterpolateLevel(){ + if(interpolateMode == INTERPOLATE_GRID){ + // calculate according to smallest gridlines + // exactly same algorithm as for drawing lines + // i.e. kinda duplicated code. + float markpow = pow(paramsPerDim,2.0); + for(int p = 0; p < paramBitDepth; p++){ + + double gridSize = pow(markpow,p); + double divsr = size.x / gridSize; + + // return the spacing + if( ofGetWidth()/divsr >= smallestGridSpacing){ + interpLevel = p; + return p; + } + } + interpLevel = 0; + return 0; + }else{ + interpLevel = 0; + return 0; // ??? + } +} +//-------------------------------------------------------------- +void Grid::draw(){ + if(interpolateMode == NO_INTERPOLATION){ + drawGridLines(); + drawPresets(); + }else if(interpolateMode == INTERPOLATE_GRID){ + // calculate according to smallest gridlines + drawGridLines(); + + }else if(interpolateMode == INTERPOLATE_PRESET){ + drawPresets(); + return; // ??? + } + + + + // draw centre cross hairs + drawCrossHairs(); + + + // draw the undo history trail, given viewing area + eventLogger.drawTrail(topLeft, topLeft + size); +} //-------------------------------------------------------------- -void Grid::draw(){ // draw lines +void Grid::drawGridLines(){ // draw lines // TODO too friggin long pixSize.setCoord(ofGetWidth(), ofGetHeight()); // incase of rotation? - //scale++; - // nice loopy thing + int power = 0; // these get big! @@ -82,24 +134,25 @@ float alpha; bool done = false; - float markpow = 32.0; // power that denotes next grid markings + float markpow = 1 << paramsPerDim; // power that denotes next grid markings e.g. 32 int lineWidth = 0; int colCycle = 0; - // loop thru powers of (base?) to determine which should be shown as grids + // loop thru powers of (base?) smallest to biggest + // to determine which should be shown as grids while (!done){ gridSize = pow(markpow,power); - colCycle = power % 7; + colCycle = power % paramBitDepth; divsr = size.x / gridSize; // if (divisor i.e. number of lines is less than 1000 - if( divsr >= 1 && divsr < 700){ + if( ofGetWidth()/divsr >= smallestGridSpacing){ // calculate transparency - float visCont = log10(divsr); // 0 if only 1 line, 3 if 1000 lines + float visCont = log10(divsr*2); // 0 if only 1 line, 3 if 1000 lines alpha = 90*(3 - visCont); ofSetLineWidth(lineWidth); @@ -199,24 +252,21 @@ } - }else if (divsr < 1){ - // ignore... + } + /*else if (divsr < 1){ + // maximum only one line. worth checking so that bigger lines still show up? done = true; } - +*/ power++; + if(power > paramBitDepth) + done = true; + } //cout << "draw done" << "\n"; //displayInfo(); - drawPresets(); - // draw centre cross hairs - drawCrossHairs(); - - - // draw the undo history trail, given viewing area - eventLogger.drawTrail(topLeft, topLeft + size); ////////-------//////// /* @@ -353,6 +403,7 @@ viewWasChanged(); + calculateInterpolateLevel(); eventLogger.logEvent(ZOOM, centre, scale); } @@ -422,7 +473,11 @@ if(snapped){ params = calculateParamsFromCoord(snapCentre); }else{ - params = calculateParamsFromCoord(centre); + if(interpolateMode == NO_INTERPOLATION){ + params = calculateParamsFromCoord(centre); + }else if(interpolateMode == INTERPOLATE_GRID){ + params = calculateInterpolatedParamsFromCoord(centre); + } } for(int i = 0;i<2*paramsPerDim;i++){ midiCC[i] = params[i]; @@ -546,7 +601,7 @@ //-------------------------------------------------------------- #pragma mark const utils -TwoVector Grid::calculateCoordFromParams(vector<int> params) const{ +TwoVector Grid::calculateCoordFromParams(vector<int> params){ vector<int> ccValueX(paramsPerDim); vector<int> ccValueY(paramsPerDim); @@ -562,7 +617,7 @@ } //-------------------------------------------------------------- -vector<int> Grid::calculateParamsFromCoord(TwoVector coord) const{ +vector<int> Grid::calculateParamsFromCoord(TwoVector coord){ if (coord.x > maxValue || coord.y > maxValue){ cout << "calculateParams Error: centre double value is too large" << "\n"; @@ -588,7 +643,59 @@ result.insert( result.end(), resultY.begin(), resultY.end() ); return result; } +//-------------------------------------------------------------- +vector<int> Grid::calculateInterpolatedParamsFromCoord(TwoVector coord){ + vector<int> result; + // round by masking according to interpLevel + + long long x = coord.x; + long long y = coord.y; + cout << interpLevel << "\n"; + int roundDigits = (paramsPerDim*interpLevel); + // knock off last digits + x = x >> roundDigits; + x = x << roundDigits; + float frac = (coord.x - x)/(1 << roundDigits); + long long xlower = x; + long long xupper = x + (1 << roundDigits); + + vector<int> pupper = hilbert.calculateParamsFromIndex(xupper); + vector<int> plower = hilbert.calculateParamsFromIndex(xlower); + + result = interpVector(pupper,plower,frac); +// now Y + y = y >> roundDigits; + y = y << roundDigits; + frac = (coord.y - y)/(1 << roundDigits); + long long ylower = y; + long long yupper = y + (1 << roundDigits); + + pupper = hilbert.calculateParamsFromIndex(yupper); + plower = hilbert.calculateParamsFromIndex(ylower); + + vector<int> resultY = interpVector(pupper,plower,frac); +// stickem together + result.insert( result.end(), resultY.begin(), resultY.end() ); + return result; +} +//-------------------------------------------------------------- +vector<int> Grid::interpVector(vector<int> upper, vector<int> lower, float frac){ + vector<int> result; + if(upper.size() != lower.size()){ + cout << "Error: interpVector takes vectors of same length" << "\n"; + return result; + } + if(frac > 1){ + cout << "Error: bad fraction for vector interpolation" << "\n"; + return result; + } + int N = upper.size(); + for(int i=0; i<N; i++){ + result.push_back(frac*upper[i] + (1-frac)*lower[i]); + } + return result; +} //-------------------------------------------------------------- vector<int> Grid::walkDiff(vector<bool> left, vector<bool> right){ // horrible