rt300@4: // rt300@4: // grid.cpp rt300@4: // oscSenderExample rt300@4: // rt300@4: // Created by Robert Tubb on 03/10/2012. rt300@4: // rt300@4: // rt300@4: rt300@4: #include "grid.h" rt300@4: rt300@4: rt300@4: #include rt300@4: rt300@4: extern PresetManager presetManager; rt300@4: extern EventLogger eventLogger; rt300@4: //-------------------------------------------------------------- rt300@4: Grid::Grid(): maxValue(pow(32.0,7.0)-1), minValue(60), paramsPerDim(5), paramBitDepth(7){ rt300@4: rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: //-------------------------------------------------------------- rt300@4: Grid::~Grid(){ rt300@4: rt300@4: } rt300@4: void Grid::init(){ rt300@4: //maxValue = pow(32.0,7.0)-1; rt300@4: //minValue = 60; // number of 1-size divisions at smallest scale rt300@4: maxZoom = false; rt300@4: minZoom = false; rt300@4: rt300@4: codeLength = pow(2.0,paramsPerDim); rt300@4: rt300@4: pixSize.setCoord(ofGetWidth(), ofGetHeight()); rt300@4: rt300@4: //set scale and position to mid way rt300@24: scale = 5500.0; rt300@8: snapDist = TwoVector(9,9); rt300@5: snapped = false; rt300@4: rt300@4: size.setCoord(pixSize.x*scale, pixSize.y*scale); rt300@4: centre.setCoord(maxValue/2 , maxValue/2); rt300@4: topLeft.setCoord(centre.x - size.x/2, centre.y - size.y/2); rt300@4: rt300@4: rt300@4: makeCode(); rt300@4: rt300@4: // set a starting param value, find coord that does it. rt300@4: vector params(paramsPerDim*2); rt300@4: for(int i = 0;i<2*paramsPerDim;i++){ rt300@4: midiCC[i] = 12; rt300@4: params[i] = 12; rt300@4: } rt300@4: TwoVector coord = calculateCoordFromParams(params); rt300@4: setCoord(coord); rt300@4: rt300@4: viewWasChanged(); rt300@4: rt300@4: rt300@4: rt300@4: } rt300@4: rt300@4: template int sgn(T val) { rt300@4: return (T(0) < val) - (val < T(0)); rt300@4: } rt300@5: //-------------------------------------------------------------- rt300@4: void Grid::makeCode(){ rt300@4: rt300@4: ////////////////////////////////~~~,,,,,,,,......... rt300@4: ////////// gray code generation rt300@4: ////// rt300@4: /// rt300@4: // TODO 5bit specific rt300@4: // transition sequence.... what a palaver! only need to do once though. rt300@4: 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@4: rt300@4: rt300@4: int code[codeLength][paramsPerDim]; // start with normal array rt300@4: rt300@4: rt300@4: rt300@4: for(int j=0; j()); rt300@4: rt300@4: for(int j=0; j >::iterator cit; rt300@4: //vector::iterator bit; rt300@4: vector::iterator bit; rt300@4: int i = 0; rt300@4: for(cit=vcode.begin(); cit!=vcode.end() ; cit++){ // fill vector rt300@4: i++; rt300@4: cout << i << " = "; rt300@4: bit = (*cit).begin(); rt300@4: for(bit=(*cit).begin(); bit!=(*cit).end() ; bit++){ rt300@4: rt300@4: cout << *bit; rt300@4: } rt300@4: cout << "\n"; rt300@4: rt300@4: } rt300@7: rt300@4: // codeToInt unit test rt300@4: vector aCode = vcode[12]; rt300@4: int result = grayToInt(aCode); rt300@4: cout << "GRAY TO INT : " << result << "\n"; rt300@4: rt300@4: cout << "-------------------------------\n"; rt300@4: rt300@4: // base32toFloat unit test rt300@4: rt300@4: vector test32 = coordTobase32(869437.0); rt300@4: double cresult = base32toCoord(test32); rt300@4: cout << "base32toCoord : " << cresult << "\n"; rt300@4: rt300@4: cout << "-------------------------------\n"; rt300@4: rt300@4: rt300@4: rt300@4: // midiToGray unit test rt300@4: rt300@4: vector > incodes(paramBitDepth, vector(paramsPerDim)); rt300@4: for(int i=0;i<7;i++){ rt300@4: incodes[i] = vcode[i+5]; rt300@4: } rt300@4: rt300@4: vector midiTest; rt300@4: midiTest = grayToMidi(incodes); rt300@4: vector > outcodes = midiToGray(midiTest); rt300@4: rt300@4: vector< vector >::iterator cit1; rt300@4: //vector::iterator bit; rt300@4: vector::iterator bit1; rt300@4: cout << "midiToGray Unit test\n"; rt300@4: for(int i=0;i checkParam; rt300@4: checkParam = calculateParamsFromCoord(inCoord); rt300@4: for(int i=0; i<2*paramsPerDim;i++){ rt300@4: cout << checkParam[i] << "_"; rt300@4: } rt300@4: TwoVector outCoord = calculateCoordFromParams(checkParam); rt300@4: cout << "Unit TEst coord = " << outCoord.x << "," << outCoord.y << "\n"; rt300@4: */ rt300@4: rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: void Grid::draw(){ // draw lines rt300@4: // TODO too friggin long rt300@4: rt300@16: pixSize.setCoord(ofGetWidth(), ofGetHeight()); // incase of rotation? rt300@4: //scale++; rt300@4: // nice loopy thing rt300@4: int power = 0; rt300@4: rt300@4: // these get big! rt300@4: double divsr; rt300@4: double yl,xl; rt300@4: double gridSize = 0; rt300@4: rt300@4: double firstLineXPos, lastLineXPos,firstLineYPos, lastLineYPos, remleft, xoffset, yoffset = 0.0; rt300@4: double xstart, xfinish, ystart,yfinish; rt300@4: // these don't rt300@4: int xpos, ypos = 0; rt300@4: rt300@4: float alpha; rt300@4: bool done = false; rt300@4: float markpow = 32.0; // power that denotes next grid markings rt300@4: int lineWidth = 0; rt300@4: int colCycle = 0; rt300@4: rt300@4: rt300@4: // loop thru powers of (base?) to determine which should be shown as grids rt300@4: while (!done){ rt300@4: gridSize = pow(markpow,power); rt300@4: rt300@4: colCycle = power % 7; rt300@4: rt300@4: divsr = size.x / gridSize; rt300@4: rt300@4: // if (divisor i.e. number of lines is less than 1000 rt300@9: if( divsr >= 1 && divsr < 700){ rt300@4: rt300@4: // calculate transparency rt300@4: float visCont = log10(divsr); // 0 if only 1 line, 3 if 1000 lines rt300@4: alpha = 90*(3 - visCont); rt300@4: ofSetLineWidth(lineWidth); rt300@4: rt300@4: // cycle colors for different scales rt300@4: if(colCycle == 0){ rt300@4: ofSetColor(255,255,255,alpha); rt300@4: }else if(colCycle == 1){ rt300@4: ofSetColor(255,0,0,alpha); rt300@4: }else if(colCycle == 2){ rt300@4: ofSetColor(0,0,255,alpha); rt300@4: }else if(colCycle == 3){ rt300@4: ofSetColor(0,255,0,alpha); rt300@4: }else if(colCycle == 4){ rt300@4: ofSetColor(255,0,255,alpha); rt300@4: }else if(colCycle == 5){ rt300@4: ofSetColor(0,255,255,alpha); rt300@4: }else if(colCycle == 6){ rt300@4: ofSetColor(255,255,0,alpha); rt300@4: }else if(colCycle == 7){ rt300@4: ofSetColor(255,255,255,alpha); rt300@4: }else{ rt300@4: cout << "err colour messed up\n"; rt300@4: } rt300@4: rt300@4: rt300@4: // draw level numbers associated with each color. This would not be true if markpow wasnt 2^d rt300@4: ////////-------///////// rt300@4: /* rt300@4: temp << "THIS LEVEL = " << (int)pow(2.0,power) << " "; rt300@4: string s = temp.str(); rt300@4: ofDrawBitmapString( s, 10, line ); rt300@4: line+=30; rt300@4: temp.str(""); rt300@4: *////////-------///////// rt300@4: rt300@4: // draw presets at this level rt300@4: // fill in smallest squares if they contain a preset rt300@4: // how to do this efficiently? rt300@4: rt300@4: rt300@4: if(topLeft.x < 0.0){ rt300@4: firstLineXPos = 0.0; rt300@4: xoffset = firstLineXPos - topLeft.x; rt300@4: xstart = xoffset/scale; rt300@4: }else{ rt300@4: firstLineXPos = topLeft.x; rt300@4: // kinda float version of % operator rt300@4: remleft = ceil(firstLineXPos/gridSize); rt300@4: xoffset = (remleft * gridSize) - topLeft.x; rt300@4: xstart = 0; rt300@4: } rt300@4: if(topLeft.x + size.x > maxValue){ rt300@4: lastLineXPos = maxValue+1 - topLeft.x; rt300@4: rt300@4: rt300@4: }else{ rt300@4: lastLineXPos = size.x; rt300@4: rt300@4: } rt300@4: xfinish = lastLineXPos/scale; rt300@4: rt300@4: //////////------------------------ rt300@4: // same for y rt300@4: rt300@4: if(topLeft.y < 0.0){ rt300@4: firstLineYPos = 0.0; rt300@4: yoffset = firstLineYPos - topLeft.y; rt300@4: ystart = yoffset/scale; rt300@4: }else{ rt300@4: firstLineYPos = topLeft.y; rt300@4: // kinda float version of % operator rt300@4: remleft = ceil(firstLineYPos/gridSize); rt300@4: yoffset = (remleft * gridSize) - topLeft.y; rt300@4: ystart = 0; rt300@4: } rt300@4: if(topLeft.y + size.y > maxValue){ rt300@4: lastLineYPos = maxValue+1 - topLeft.y; rt300@4: rt300@4: }else{ rt300@4: lastLineYPos = size.y; rt300@4: rt300@4: } rt300@4: yfinish = lastLineYPos/scale; rt300@4: // ------------------------------------------- rt300@4: // now draw rt300@4: for(xl = xoffset; xl <= (lastLineXPos); xl+= gridSize){ rt300@4: rt300@4: xpos = xl/scale; rt300@4: ofLine(xpos, ystart, xpos, yfinish); rt300@4: rt300@4: } rt300@4: rt300@4: for(yl = yoffset; yl <= (lastLineYPos); yl+= gridSize){ rt300@4: rt300@4: ypos = yl/scale; rt300@4: ofLine(xstart, ypos, xfinish, ypos); rt300@4: } rt300@4: rt300@4: rt300@4: }else if (divsr < 1){ rt300@4: // ignore... rt300@4: done = true; rt300@4: } rt300@4: rt300@4: power++; rt300@4: } rt300@4: //cout << "draw done" << "\n"; rt300@4: //displayInfo(); rt300@4: rt300@4: drawPresets(); rt300@4: ////////-------///////// rt300@4: rt300@4: ////////-------///////// rt300@4: rt300@4: // draw centre cross hairs rt300@5: drawCrossHairs(); rt300@4: ////////-------//////// rt300@4: /* rt300@4: ostringstream temp; rt300@4: temp << "Centre x = " << centre.x << "\n y = " << centre.y << " "; rt300@4: string s = temp.str(); rt300@4: ofDrawBitmapString( s, pixSize.x/2+10, pixSize.y/2+10 ); rt300@4: */ rt300@4: } rt300@5: //----------------------------------------------------------------------- rt300@5: void Grid::drawCrossHairs(){ rt300@5: // snapping rt300@5: TwoVector pos; rt300@5: if(snapped){ rt300@5: pos = coordToPixel(snapCentre); rt300@5: }else{ rt300@5: pos = coordToPixel(centre); rt300@5: rt300@5: } rt300@5: ofSetColor(255, 0, 0); rt300@5: ofNoFill(); rt300@5: ofLine(pos.x-20, pos.y, pos.x+20, pos.y); rt300@5: ofLine(pos.x, pos.y-20, pos.x, pos.y+20); rt300@5: ofEllipse(pos.x, pos.y, 20, 20); rt300@5: ofFill(); rt300@5: } rt300@5: //----------------------------------------------------------------------- rt300@4: TwoVector Grid::coordToPixel(TwoVector coord){ rt300@4: TwoVector pix; rt300@4: pix.x = (coord.x - topLeft.x)/scale; rt300@4: pix.y = (coord.y - topLeft.y)/scale; rt300@4: return pix; rt300@4: rt300@4: } rt300@4: rt300@4: //----------------------------------------------------------------------- rt300@4: void Grid::drawPresets(){ rt300@5: presetManager.drawPresetsInRange(topLeft, topLeft + size); rt300@7: // draw snapped preset info rt300@7: if(snapped && closestPreset != NULL){ rt300@8: ofDrawBitmapString( closestPreset->displayTextDescription(), pixSize.x/2+10, pixSize.y/2+10 ); rt300@7: } rt300@4: } rt300@4: rt300@4: //----------------------------------------------------------------------- rt300@4: void Grid::displayInfo(){ rt300@4: rt300@4: // display some "useful information" rt300@4: rt300@4: ofSetColor(255,255,255,255); rt300@4: rt300@4: ostringstream temp; rt300@4: int line = 10; // text output pos rt300@4: rt300@4: rt300@4: ////////-------///////// rt300@4: temp << "scale = " << scale << " "; rt300@4: string s = temp.str(); rt300@4: ofDrawBitmapString( s, 10, line ); rt300@4: line+=30; rt300@4: temp.str(""); rt300@4: ////////-------///////// rt300@4: temp << "Top Left = " << topLeft.x << "," << topLeft.y << " "; rt300@4: s = temp.str(); rt300@4: ofDrawBitmapString( s, 10, line ); rt300@4: line+=60; rt300@4: temp.str(""); rt300@4: rt300@4: ////////-------///////// rt300@4: temp << "View Size = " << size.x << "," << size.y << " "; rt300@4: s = temp.str(); rt300@4: ofDrawBitmapString( s, 10, line ); rt300@4: line+=60; rt300@4: temp.str(""); rt300@4: rt300@4: ////////-------///////// rt300@4: rt300@4: for(int i=0;i<10;i++){ // TODO 5bit specific rt300@4: temp << midiCC[i] << " "; rt300@4: s = temp.str(); rt300@4: ofDrawBitmapString( s, 10, line ); rt300@4: line+=20; rt300@4: temp.str(""); rt300@4: } rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: void Grid::update(){ // ? rt300@4: // "update" bit of a crap name - all we do here is calculate the dimension params from the x,y position rt300@4: rt300@4: rt300@4: } rt300@5: rt300@4: //-------------------------------------------------------------- rt300@24: // would be advisable to only have one "mover" object that has permission to move the grid (?) rt300@4: void Grid::move(TwoVector moveP){ rt300@4: // numspacing, pixelspacing stay the same rt300@4: rt300@4: // convert pixels to surf units rt300@4: TwoVector moveS; rt300@4: moveS = moveP * scale; rt300@4: rt300@4: topLeft = topLeft - moveS; // - because moving to the right means taking away from offset rt300@4: centre = centre - moveS; rt300@4: rt300@4: viewWasChanged(); rt300@5: eventLogger.logEvent(SCROLL, centre, scale); rt300@4: rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: void Grid::zoom(float factor){ rt300@5: if(snapped)centre = (centre + snapCentre)*0.5; // clunky rt300@5: rt300@4: if(maxZoom && factor > 1.0){ rt300@4: return; rt300@4: rt300@4: } rt300@4: if(factor < 1.0){ rt300@4: maxZoom = false; rt300@4: } rt300@4: if(minZoom && factor < 1.0){ rt300@4: return; rt300@4: rt300@4: } rt300@4: if(factor > 1.0){ rt300@4: minZoom = false; rt300@4: } rt300@4: scale = scale*factor; // simple eh? rt300@4: rt300@4: // update view size using centre rt300@4: // and scale... rt300@4: size.x = size.x*factor; // zooming in, size gets SMALLER (view less) rt300@4: size.y = size.y*factor; rt300@4: rt300@4: rt300@4: rt300@4: viewWasChanged(); rt300@5: eventLogger.logEvent(ZOOM, centre, scale); rt300@4: rt300@5: } rt300@5: //-------------------------------------------------------------- rt300@20: void Grid::shiftCentreToSnapped(){ rt300@20: // TODO just in case we're freezing something rt300@20: // snapping actually change centre rt300@20: centre = snapCentre; rt300@20: rt300@20: } rt300@20: //-------------------------------------------------------------- rt300@5: void Grid::snapCheck(){ rt300@5: // check environs for presets. rt300@7: rt300@5: vector closePresets = presetManager.getPresetsInRange(centre - snapDist*scale, centre + snapDist*scale); rt300@5: if(closePresets.size() > 0){ rt300@5: snapped = true; rt300@5: // find closest rt300@5: double dist, mindist = maxValue; rt300@5: closestPreset = closePresets[0]; rt300@5: rt300@5: for(vector::iterator piter = closePresets.begin(); piter < closePresets.end(); piter++){ rt300@5: dist = (*piter)->coordinates.distanceTo(centre); rt300@5: rt300@5: if(dist < mindist){ rt300@5: mindist = dist; rt300@5: closestPreset = *piter; rt300@5: } rt300@5: } rt300@5: snapCentre = closestPreset->coordinates; rt300@22: eventLogger.logEvent(SNAPPED_TO_PRESET, getCoord(),closestPreset->creationTime ); rt300@22: cout << "SNAPPED CHECK\n"; rt300@5: }else{ rt300@5: snapped = false; rt300@7: closestPreset = NULL; rt300@5: snapCentre = centre; rt300@5: } rt300@5: rt300@4: rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@5: void Grid::setMaxZoom(){ // got to smallest (white) rt300@5: if(snapped)centre = snapCentre; rt300@5: size.x = maxValue*2.0; rt300@5: scale = size.x/pixSize.x; rt300@5: size.y = scale * pixSize.y; rt300@7: maxZoom = true; rt300@7: minZoom = false; rt300@5: viewWasChanged(); rt300@5: } rt300@5: //-------------------------------------------------------------- rt300@5: void Grid::setMinZoom(){ // go to entire space (orange) rt300@5: if(snapped)centre = snapCentre; rt300@5: size.x = minValue*2.0; rt300@5: scale = size.x/pixSize.x; rt300@5: size.y = scale * pixSize.y; rt300@7: minZoom = true; rt300@7: maxZoom = false; rt300@5: viewWasChanged(); rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: void Grid::viewWasChanged(){ rt300@5: snapCheck(); rt300@4: checkLimits(); rt300@5: // calculate new params? rt300@5: vector params; rt300@5: if(snapped){ rt300@5: params = calculateParamsFromCoord(snapCentre); rt300@5: }else{ rt300@5: params = calculateParamsFromCoord(centre); rt300@5: } rt300@4: for(int i = 0;i<2*paramsPerDim;i++){ rt300@4: midiCC[i] = params[i]; rt300@4: } rt300@4: rt300@4: } rt300@4: rt300@4: //-------------------------------------------------------------- rt300@4: void Grid::checkLimits(){ rt300@4: // check for maximum zoom level rt300@5: rt300@4: rt300@4: if(size.x > maxValue*2.0){ rt300@4: cout << "maxZoom\n"; rt300@4: maxZoom = true; rt300@4: size.x = maxValue*2.0; rt300@4: // need to also set y size back to rt300@4: } rt300@4: if(size.y > maxValue*2.0){ rt300@4: cout << "maxZoom\n"; rt300@4: maxZoom = true; rt300@4: size.y = maxValue*2.0; rt300@4: } rt300@4: rt300@4: if(size.x < minValue){ rt300@4: cout << "min Zoom\n"; rt300@4: minZoom = true; rt300@4: size.x = minValue; rt300@4: // need to also set y size back to rt300@4: } rt300@4: if(size.y < minValue){ rt300@4: minZoom = true; rt300@4: cout << "min Zoom\n"; rt300@4: size.y = minValue; rt300@4: } rt300@4: rt300@4: scale = size.x/pixSize.x; rt300@4: size.y = scale * pixSize.y; rt300@4: rt300@4: topLeft.x = centre.x - size.x/2; rt300@4: topLeft.y = centre.y - size.y/2; rt300@4: // check for negatives rt300@4: rt300@4: // allow centre to be at limits rt300@4: if((topLeft.x + size.x*0.5) < 0.0){ rt300@4: cout << "left Wall\n"; rt300@4: topLeft.x = 0.0 - size.x*0.5; rt300@4: centre.x = 0.0; rt300@4: } rt300@4: rt300@4: if(topLeft.y + size.y*0.5 < 0.0) { rt300@4: cout << "top Wall\n"; rt300@4: topLeft.y = 0.0 - size.y*0.5; rt300@4: centre.y = 0.0; rt300@4: } rt300@4: rt300@4: // does topleft refer to lines or view? rt300@4: rt300@4: // check max rt300@4: if(topLeft.x + size.x/2 > maxValue){ rt300@4: cout << "right Wall\n"; rt300@4: topLeft.x = maxValue - size.x/2; rt300@4: centre.x = maxValue; rt300@4: } rt300@4: if(topLeft.y + size.y/2 > maxValue) { rt300@4: cout << "bottom Wall\n"; rt300@4: topLeft.y = maxValue - size.y/2; rt300@4: centre.y = maxValue; rt300@4: } rt300@4: rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: void Grid::checkConsistencies(){ rt300@4: // debug function to check all the parameters are consistent maybe rt300@4: rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: void Grid::setCoord(TwoVector coord){ rt300@4: rt300@4: centre = coord; rt300@5: rt300@4: viewWasChanged(); rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: TwoVector Grid::getCoord(){ rt300@5: // return read point crosshairs rt300@5: if(snapped){ rt300@5: return snapCentre; rt300@5: } rt300@4: return centre; rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: vector Grid::getParams(){ rt300@4: // return a vector with midiCCs in rt300@4: // should we store params somewhere and use this as a low computation get ? rt300@4: vector params(2*paramsPerDim,0); rt300@4: // rt300@4: for(int i = 0;i<2*paramsPerDim;i++){ rt300@4: params[i] = midiCC[i]; rt300@4: } rt300@4: return params; rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: void Grid::setParams(vector params){ rt300@4: // input midiCCs, and go to the appropriate coordinate rt300@4: rt300@4: for(int i = 0;i<2*paramsPerDim;i++){ rt300@4: midiCC[i] = 64; rt300@4: } rt300@4: TwoVector coord = calculateCoordFromParams(params); rt300@4: setCoord(coord); rt300@4: rt300@20: // snapping? rt300@4: viewWasChanged(); rt300@4: rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@5: //-------------------------------------------------------------- rt300@5: //-------------------------------------------------------------- rt300@5: //-------------------------------------------------------------- rt300@5: //-------------------------------------------------------------- rt300@5: #pragma mark const utils rt300@5: rt300@4: TwoVector Grid::calculateCoordFromParams(vector params) const{ rt300@4: rt300@4: vector ccValueX(paramsPerDim); rt300@4: vector ccValueY(paramsPerDim); rt300@4: for(int i=0;i > codesX = midiToGray(ccValueX); rt300@4: vector > codesY = midiToGray(ccValueY); rt300@4: rt300@4: vector base32X = codesToBase32(codesX); rt300@4: vector base32Y = codesToBase32(codesY); rt300@4: rt300@4: TwoVector result; rt300@4: result.x = base32toCoord(base32X); rt300@4: result.y = base32toCoord(base32Y); rt300@4: return result; rt300@4: } rt300@4: rt300@4: //-------------------------------------------------------------- rt300@4: vector Grid::calculateParamsFromCoord(TwoVector coord) const{ rt300@4: // some arrays in reverse order of power from normal numbers! 1,2,4, rt300@4: rt300@4: // centre to base 32 rt300@4: if (coord.x > maxValue || coord.y > maxValue){ rt300@4: cout << "calculateParams Error: centre double value is too large" << "\n"; rt300@4: vector empty; rt300@4: return empty; rt300@4: } rt300@4: rt300@4: //-------------------------- rt300@4: // X rt300@4: vector base32x = coordTobase32(coord.x); // 7 numbers from 0 to 31 rt300@4: vector > grayCodesX; rt300@4: rt300@4: int size = base32x.size(); rt300@4: for(int i=0;i result; rt300@4: result = grayToMidi(grayCodesX); rt300@4: //-------------------------- rt300@4: // AND FOR Y rt300@4: vector base32y = coordTobase32(coord.y); rt300@4: vector > grayCodesY; rt300@4: rt300@4: size = base32y.size(); rt300@4: for(int i=0;i resultY; rt300@4: resultY = grayToMidi(grayCodesY); rt300@4: rt300@4: // concatenate rt300@4: result.insert( result.end(), resultY.begin(), resultY.end() ); rt300@4: return result; rt300@4: } rt300@4: //------------------------------------------------------------------- rt300@4: rt300@4: // for 1 dimension!!! i.e. call this twice rt300@4: vector Grid::grayToMidi(vector > grayCodes) const{ rt300@4: rt300@4: // gray to midi CC values rt300@4: // loop thru the scales to build up a CC number per dimension rt300@4: int midiCCresult[paramsPerDim]; // TODO dims specific rt300@4: for(int i=0;i >::iterator piter = grayCodes.begin(); rt300@4: for(;piter < grayCodes.end();piter++){ // each lesser power of 2 rt300@4: midP = 0; // reset rt300@4: vector::iterator diter = (*piter).begin(); rt300@4: for(; diter <= (*piter).end();diter++){ // each one is different dimension rt300@4: int ig = int(*diter); // convert binary to int rt300@4: //cout << "ig: " << ig; rt300@4: midiCCresult[midP] += ig*bin; // mult by power of two rt300@4: midP++; rt300@4: } rt300@4: bin = bin >> 1; // next power of 2 down rt300@4: rt300@4: } rt300@4: rt300@4: // put in vector rt300@4: vector result; rt300@4: for(int i=0;i Grid::intToGray(int num, int dimToTravel) const{ rt300@4: rt300@4: // dimToTravel - this is the dimension that we want the walk to traverse, i.e. the last non zero digit of the code rt300@4: // so swap it for 3 to produce correct orientation rt300@4: rt300@4: // just use look up table... until it gets huuuge. rt300@4: vector grayCode = vcode[num]; rt300@4: grayCode[3] = vcode[num][dimToTravel]; rt300@4: grayCode[dimToTravel] = vcode[num][3]; rt300@4: return grayCode; rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: vector Grid::walkDiff(vector left, vector right){ rt300@4: // horrible rt300@4: vector result(2,0); rt300@4: rt300@4: int size = left.size(); rt300@4: for(int i = 0; i < size; i++){ rt300@4: if(left[i] && !right[i]){ // 1 - 0 rt300@4: // dim rt300@4: result[0] = i; rt300@4: result[1] = 1; rt300@4: }else if(!left[i] && right[i]){ // 0 - 1 rt300@4: result[0] = i; rt300@4: result[1] = -1; rt300@4: }else{ // equal do nothing rt300@4: rt300@4: rt300@4: } rt300@4: } rt300@4: rt300@4: return result; rt300@4: } rt300@4: rt300@4: //-------------------------------------------------------------- rt300@4: /* rt300@4: breaks down float into a base 32 number (2^D) rt300@4: each of these is converted to gray code rt300@4: this is then converted to 10 parameters, where each 32-digit becomes separate power of 2 rt300@4: so "zoom" grid 32-patches are converted to 2-scales. 1,2,4,8,16,32,64,(128?) biggest number is 32^7 rt300@4: */ rt300@4: vector Grid::coordTobase32(double value) const{ rt300@4: //double base = 32.0; rt300@4: if(value < 0.0){ rt300@4: cout << "coordTobase32 error: input value is negative\n"; rt300@4: value = 0.0; rt300@4: }else if(value > maxValue){ rt300@4: cout << "coordTobase32 error: input value too big!\n"; rt300@4: } rt300@4: double rem, divdr = 0.0; rt300@4: int digit32; rt300@4: rt300@4: // what power of 32 to start at? rt300@4: int maxpow = 7; // midi cc specific rt300@4: vector result; rt300@4: rt300@4: rem = value; rt300@4: for(;maxpow >=0;maxpow--){ rt300@4: // repeatedly get digit and remainder. This is exactly what we're doing in draw !?... could put all this in one place? rt300@4: divdr = pow((double)codeLength,(double)maxpow); rt300@4: digit32 = floor(rem/divdr); rt300@4: rem = rem - digit32*divdr; rt300@4: result.push_back(digit32); // array, biggest index is smallest power rt300@4: } rt300@4: // at this point rem should be fractional... use for interp? rt300@4: rt300@4: return result; rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: rt300@4: vector Grid::codesToBase32(vector > inCodes) const{ rt300@4: vector result; rt300@4: for(int i=0;i incode) const{ rt300@4: // look for match in table rt300@4: rt300@4: int s = vcode.size(); rt300@4: rt300@4: for(int i=0; i base32Digs) const{ rt300@4: // build up the big float from a base 32 number rt300@4: double result = 0.0; rt300@4: rt300@4: // what power of 32 to start at? rt300@4: int mpow = base32Digs.size() - 1; // should be 7... rt300@4: rt300@4: for(int p=0;p<=mpow;p++){ // biggest index is smallest power rt300@4: result += ((double)base32Digs[p]) * pow(32.0, (double)mpow-p); rt300@4: rt300@4: } rt300@4: return result; rt300@4: rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: // for 1 dimension - takes in 5 cc params and outputs 7 codes rt300@4: vector > Grid::midiToGray(vector ccValue) const{ rt300@4: int pow2 = 1 << (paramBitDepth-1); rt300@4: rt300@4: vector aCode(paramsPerDim); rt300@4: vector > theXCodes(paramBitDepth,aCode); rt300@4: rt300@4: // build up binary gray code representations from the bits of the midi ccs rt300@4: rt300@4: vector > theCodes(paramBitDepth, vector(paramsPerDim)); rt300@4: rt300@4: // x rt300@4: for(int p=0;p> 1; rt300@4: rt300@4: } rt300@4: return theCodes; rt300@4: } rt300@4: //-------------------------------------------------------------- rt300@4: //-------------------------------------------------------------- rt300@4: //--------------------------------------------------------------