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