More Utils

Hey just wanted to start a list of function to add to the utils. Here are some that I have based on processing:

  
  
#include "ofConstants.h"  
#include "ofMain.h"  
  
//-------------------------------------------------- Graphic Utils  
  
void	ofDrawFPS(int x=15, int y=ofGetHeight()-35);  
  
//-------------------------------------------------- Math Utils  
  
float	ofNorm(float value, float start, float stop);  
float	ofMap(float value, float istart, float istop, float ostart, float ostop);  
float	ofDist(float a, float b, float c, float d);  
int		ofConstrain(int amt, int low, int high);  
float	ofSq(float n);  
float	ofDegrees(float radians);  
float	ofRadians(float degrees);  
float	ofLerp(float start, float stop, float amt);  
float	dist(float x1, float y1, float x2, float y2);  
float	dist(float x1, float y1, float z1, float x2, float y2, float z2);  
  
//-------------------------------------------------- Other Utils  
  
float ofRanWidth();  
float ofRanHeight();  
  

  
  
//-------------------------------------------------- Graphic Utils  
  
void ofDrawFPS(int x=15, int y=ofGetHeight()-35) {  
	glPushMatrix();  
	glTranslatef(x, y, 0);  
	ofSetRectMode(OF_RECTMODE_CORNER);  
	ofFill();  
	ofSetColor(0x000000);  
	ofSetColor(0, 255, 0);  
	string fpsStr = "FPS: "+ofToString(ofGetFrameRate(), 2);  
	ofDrawBitmapString(fpsStr, 0, 0);  
	glPopMatrix();  
}  
  
//-------------------------------------------------- Math Utils  
  
float ofNorm(float value, float start, float stop) {  
	return (value - start) / (stop - start);  
}  
  
float ofMap(float value, float istart, float istop, float ostart, float ostop) {  
	return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));  
}  
  
float ofDist(float a, float b, float c, float d) {  
	return sqrt(double((a - c) * (a - c) + (b - d) * (b - d)));  
}  
  
int ofConstrain(int amt, int low, int high) {  
	return (amt < low) ? low : ((amt > high) ? high : amt);  
}  
  
float ofSq(float n) {  
	return n*n;  
}  
  
float ofDegrees(float radians) {  
	return radians * RAD_TO_DEG;  
}  
  
float ofRadians(float degrees) {  
    return degrees * DEG_TO_RAD;  
}  
  
float ofLerp(float start, float stop, float amt) {  
    return start + (stop-start) * amt;  
}  
  
float dist(float x1, float y1, float x2, float y2) {  
    return sqrt(ofSq(x2-x1) + ofSq(y2-y1));  
}  
  
float dist(float x1, float y1, float z1, float x2, float y2, float z2) {  
    return sqrt(ofSq(x2-x1) + ofSq(y2-y1) + ofSq(z2-z1));  
}  
  
//-------------------------------------------------- Other Utils  
  
float ofRanWidth() {  
	return ofRandom(0, ofGetWidth());  
}  
float ofRanHeight() {  
	return ofRandom(0, ofGetHeight());  
}  
  

maybe we can start a wiki page that might be a better solution.

T

Here’s my ofxProcessing.h:

  
  
#ifndef OFXPROCESSING_H_INCLUDED  
#define OFXPROCESSING_H_INCLUDED  
  
// Output: Text Area: print() and println()  
  
void ofPrint(const char* str) {  
	printf("%s", str);  
}  
  
void ofPrint(string &str) {  
	printf("%s", str.c_str());  
}  
  
void ofPrint(int i) {  
	printf("%i", i);  
}  
  
void ofPrint(float f) {  
	printf("%f", f);  
}  
  
void ofPrint(bool b) {  
	printf("%s", b ? "true" : "false");  
}  
  
void ofPrint(char c) {  
	printf("%c", c);  
}  
  
template <class T>  
void ofPrint(vector<T> &vec) {  
	ofPrint("{ ");  
	for(int i = 0; i < vec.size(); i++) {  
		ofPrint(vec.at(i));  
		ofPrint(", ");  
	}  
	ofPrint("}");  
}  
  
void ofPrintln() {  
	ofPrint("\n");  
}  
  
template <typename T>  
void ofPrintln(T &obj) {  
	ofPrint(obj);  
	ofPrintln();  
}  
  
template <typename T>  
void ofPrintln(T* obj) {  
	ofPrint(obj);  
	ofPrintln();  
}  
  
// Output: Image: save(), saveFrame()  
  
void ofSave(char* filename) {  
	ofImage screen;  
	screen.allocate(ofGetWidth(), ofGetHeight(), OF_IMAGE_COLOR);  
	screen.grabScreen(0, 0, ofGetWidth(), ofGetHeight());  
	screen.saveImage(filename);  
}  
  
int saveImageCounter = 0;  
void ofSaveFrame() {  
	char* filename = new char[255];  
	sprintf(filename, "screen-%0.2i.tif", saveImageCounter++);  
	ofSave(filename);  
	delete filename;  
}  
  
// Shapes: ellipse() with strokeWeight and CENTER/CORNER  
  
#define OF_ELLIPSE_CENTER 0  
#define OF_ELLIPSE_CORNER 1  
float ofEllipse(float x, float y, float w, float h, int mode) {  
	switch(mode) {  
		case OF_ELLIPSE_CENTER:  
			ofEllipse(x, y, w, h);  
		break;  
		case OF_ELLIPSE_CORNER:  
			ofEllipse(x + w, y + h, w, h);  
		break;  
	}  
}  
  
// Transform  
  
void ofRotate(float r) {  
	glRotatef(ofDegrees(r), 0, 0, 1);  
}  
  
void ofRotateX(float r) {  
	glRotatef(ofDegrees(r), 1, 0, 0);  
}  
  
void ofRotateY(float r) {  
	glRotatef(ofDegrees(r), 0, 1, 0);  
}  
  
void ofRotateZ(float r) {  
	glRotatef(ofDegrees(r), 0, 0, 1);  
}  
  
// Math: Calculation: map(), sq(), constrain(), dist(), mag()  
  
float ofMap(float x, float lowIn, float highIn, float lowOut, float highOut) {  
	return ((x - lowIn) / (highIn - lowIn)) * (highOut - lowOut) + lowOut;  
}  
  
float ofConstrain(float x, float low, float high) {  
	return x < low ? low : x > high ? high : x;  
}  
  
float ofDist(float x1, float y1, float x2, float y2) {  
	float a = x2 - x1;  
	float b = y2 - y1;  
	return sqrt(a * a + b * b);  
}  
  
float ofMag(float x, float y) {  
	return ofDist(0, 0, x, y);  
}  
  
float ofRandom(float max) {  
	return ofRandom(0, max);  
}  
  
#endif // OFXPROCESSING_H_INCLUDED  
  

The ofPrint and ofPrintln stuff isn’t exactly right, but works the way I expect most of the time.

Slight difference from Processing: ofSaveFrame() doesn’t accept an argument, and increments the counter each file instead of using the frame number.

Also, Todd: why do you have ofDist() and dist()?

These are cool and would be awesome to have them in core. In addition to these, heres a few more that I use:

  
  
  
// return sign of the number  
int ofSign(float n) {  
   return n < 0 ? -1 : n > 0 : 1 : 0;  
}  
  
// checks to see if number is in range  
bool ofInRange(float t, float min, float max) {  
   return t>=min && t<=max;  
}  
  
  
// clamp a number   
// i use clamp instead of constrain cos easier to type :P  
// and its clamp in glsl   
float ofClamp(float x, float min, float max) {  
   return x < min ? min : x > max ? max : x;  
}   
  
  
float ofClamp(float x, float max) {  
   return ofClamp(x, -max, max);  
}  
  
  
// smooth normalized number  
// with hermite interpolation  
// only really works if t is 0...1 but best not to clamp here  
float ofSmooth(t) {  
   return  t * t * (3 – 2 * t);  
}  
  
  
// clamp a number between min, max  
// and smooth with hermite interpolation  
float ofSmoothClamp(t, min, max) {  
   float clamped = ofClamp(t, min, max);  
   float normed  = ofNorm(clamped, min, max);  
   float smoothed = ofSmooth(normed);  
   return ofLerp(min, max, smoothed);  
}  
  
  
  
// square of distance between two points  
// cos checking distance against square is a lot faster than doing squareroot when you dont need it  
float ofDist2(float x1, float y1, float x2, float y2) {  
   float dx = x2 - x1;  
   float dy = y2 - y1;  
   return dx*dx + dy*dy;  
}   
  
float ofDist2(float x1, float y1, float z1, float x2, float y2, float z3) {  
   float dx = x2 - x1;  
   float dy = y2 - y1;  
   float dz = z2 - z1;  
   return dx*dx + dy*dy + dz*dz;  
}   
  
  
  
// Get screen coordinates, I remember having problems with this but it should work  
// also its more efficient to calculate all 3 in one go,   
// but have the 3 individual functions for processing compatibility  
  
float ofScreenX(float x, float y, float z) {  
	GLdouble ret_x, ret_y, ret_z;  
	  
	// arrays to hold matrix information  
	GLdouble model_view[16];  
	glGetDoublev(GL_MODELVIEW_MATRIX, model_view);  
	  
	GLdouble projection[16];  
	glGetDoublev(GL_PROJECTION_MATRIX, projection);  
	  
	GLint viewport[4];  
	glGetIntegerv(GL_VIEWPORT, viewport);  
	  
	// get 3D coordinates based on window coordinates  
	gluProject(x, y, z, model_view, projection, viewport, &ret_x, &ret_y, &ret_z);  
	return ret_x;  
}  
  
  
float ofScreenY(float x, float y, float z) {  
	GLdouble ret_x, ret_y, ret_z;  
	  
	// arrays to hold matrix information  
	GLdouble model_view[16];  
	glGetDoublev(GL_MODELVIEW_MATRIX, model_view);  
	  
	GLdouble projection[16];  
	glGetDoublev(GL_PROJECTION_MATRIX, projection);  
	  
	GLint viewport[4];  
	glGetIntegerv(GL_VIEWPORT, viewport);  
	  
	// get 3D coordinates based on window coordinates  
	gluProject(x, y, z, model_view, projection, viewport, &ret_x, &ret_y, &ret_z);  
	return ret_y;  
}  
  
float ofScreenZ(float x, float y, float z) {  
	GLdouble ret_x, ret_y, ret_z;  
	  
	// arrays to hold matrix information  
	GLdouble model_view[16];  
	glGetDoublev(GL_MODELVIEW_MATRIX, model_view);  
	  
	GLdouble projection[16];  
	glGetDoublev(GL_PROJECTION_MATRIX, projection);  
	  
	GLint viewport[4];  
	glGetIntegerv(GL_VIEWPORT, viewport);  
	  
	// get 3D coordinates based on window coordinates  
	gluProject(x, y, z, model_view, projection, viewport, &ret_x, &ret_y, &ret_z);  
	return ret_z;  
}  
  
  
void ofScreenXYZ(float x, float y, float z, GLdouble &ret_x, GLdouble &ret_y, GLdouble &ret_z) {  
	// arrays to hold matrix information  
	GLdouble model_view[16];  
	glGetDoublev(GL_MODELVIEW_MATRIX, model_view);  
	  
	GLdouble projection[16];  
	glGetDoublev(GL_PROJECTION_MATRIX, projection);  
	  
	GLint viewport[4];  
	glGetIntegerv(GL_VIEWPORT, viewport);  
	  
	// get 3D coordinates based on window coordinates  
	gluProject(x, y, z, model_view, projection, viewport, &ret_x, &ret_y, &ret_z);  
}  
  
  
  

This one is good for saving out screen grabs.

  
string ofGetUniqueStringID() {  
		return  ofToString(ofGetMonth())+ofToString(ofGetDay())+ofToString(ofGetYear())+ofToString(ofGetHours())+ofToString(ofGetMinutes())+ofToString(ofGetSeconds());  
	}  

006, I see:

  
  
//check for division by zero???  
//--------------------------------------------------  
float ofMap(float value, float inputMin, float inputMax, float outputMin, float outputMax) {  
   return ((value - inputMin) / (inputMax - inputMin) * (outputMax - outputMin) + outputMin);  
}  
  

I think this is the proper solution:

  
  
float ofMap(float value, float inputMin, float inputMax, float outputMin, float outputMax) {  
	if(inputMin == inputMax)  
		return numeric_limits<float>::quiet_NaN();  
  return ((value - inputMin) / (inputMax - inputMin) * (outputMax - outputMin) + outputMin);  
}  
  

This way a quiet NaN is propagated, rather than an -1.#IND00

You could also return outputMin, I suppose – but that would create weird discontinuities that would be hard to track down.

good idea

Wrapping sscanf to implement some more Processing functions:

  
  
// Conversion: unhex(), int(), float()  
  
#include <cstdio>  
  
unsigned ofUnhex(const string& hexString) {  
	unsigned x;  
	std::sscanf(hexString.c_str(), "%x", &x);  
	return x;  
}  
  
int ofInt(const string& intString) {  
	int x;  
	std::sscanf(intString.c_str(), "%d", &x);  
	return x;  
}  
  
float ofFloat(const string& floatString) {  
	float x;  
	std::sscanf(floatString.c_str(), "%f", &x);  
	return x;  
}  
  

Poco also has Poco::NumberParser, but it gave me some weird results and crashes on floats…

Hmm… could I maybe propose an ofxUtils add-on to consolidate all of the utility methods everyone has been writing?

I’m also thinking about an ofxGraphicsAux add-on for providing additional graphic and image functions.

a while ago, i started a ofMoreUtils at ofx-dev to achieve this goal, it might be a good start…
http://github.com/lian/ofx-dev/tree/mas-…-fMoreUtils

I feel like there are a lot of utilities that could be written for oF.

But I’d mostly just like to see oF gain some of the things it’s missing compared to Processing (hence ofxProcessing).

Perhaps there could be two different threads:

1 This thread can continue, and since it’s under “feature requests”, it can be a place to suggest utility functions that would be nice to have included in the core.

2 Another thread, for compiling all the other wonderful utilities that might be dreamed up (e.g.: ofxGraphicsAux)

I have some more:

  
  
string ofGetFileExtension(string filename) {  
    int pos = filename.rfind('.');  
    if (pos==string::npos) return "";  
    return filename.substr(pos);  
}  
  
bool ofFileExists(string filename) {  
	ifstream inp;  
	inp.open(filename.c_str(), ifstream::in);  
	inp.close();  
	return !inp.fail();  
}  
  
string ofAddTrailingSlash(string foldername) {  
    if (foldername.length()==0) return "";  
    if (foldername[foldername.length()-1]=='/') return foldername;  
    else return foldername + "/";  
}  
  
template <typename T> string ofFormatString(string format, T number) {  
    char buffer[100];  
	sprintf(buffer, format.c_str(), number);  
	return (string)buffer;  
}  
  
void ofAppendToFile(string filename, string str) {  
    if (filename=="") die("ofAppendToFile:no filename");  
    FILE * pFile;  
    pFile = fopen (filename.c_str(),"a");  
    if (pFile==NULL) die("ofAppendToFile:could not open file: " + filename);  
    else fprintf (pFile, str.c_str());  
    fclose(pFile);  
}  
  
vector<string> ofReadLines(string filename) {  
    vector<string> lines;  
    filename = ofToDataPath(filename);  
    if (!ofFileExists(filename)) die("ofReadLines: File not found: " + filename);  
    ifstream f(filename.c_str(),ios::in);  
    string line;  
    while (getline(f,line)) lines.push_back(line);  
    f.close();  
    return lines;  
}  
  
vector<string> ofReadFiles(string folder) {  
    vector<string> filenames;  
    folder = ofToDataPath(folder);  
	ofxDirList files;  
    files.setVerbose(false);  
    int count = files.listDir(folder);  
    for (int i=0; i<count; i++) filenames.push_back(files.getName(i));  
    return filenames;  
}  
  
bool ofKeyAlt() {  
    return (glutGetModifiers() & GLUT_ACTIVE_ALT);  
}  
  
bool ofKeyShift() {  
    return (glutGetModifiers() & GLUT_ACTIVE_SHIFT);  
}  
  
bool ofKeyControl() {  
    return (glutGetModifiers() & GLUT_ACTIVE_CTRL);  
}  
  
void ofSetColor(int hexColor, float a) { //alpha between 0..1  
	int r = (hexColor >> 16) & 0xff;  
	int g = (hexColor >> 8) & 0xff;  
	int b = (hexColor >> 0) & 0xff;  
	ofSetColor(r,g,b,(int)(a*255));  
}  
  
void ofBackground(int hexColor) { // hex, like 0xFF0033; // rick 13-4-2008  
    int r = (hexColor >> 16) & 0xff;  
	int g = (hexColor >> 8) & 0xff;  
	int b = (hexColor >> 0) & 0xff;  
    ofBackground(r,g,b);  
}  
  
int ofAtLeast(int value, int atLeastValue) {  
    return max(value, atLeastValue);  
}  
  
int ofMakeEven(int n) {  
    return (n/2)*2;  
}  
  

Wow, how did I not know string::rfind()? Thanks!

Also, this should be equivalent and faster:

  
  
int ofMakeEven(int n) {  
    return n & ~1;  
}  
  

It just turns “off” the last bit.

hey folks,

i don’t know if this has been already posted somewhere else.
but here is a win32 implementation of how to totally undecorate the window.
for now it only supports windows and single windows.
you can also decorate them again, you just need to find out the windowstyles to add or remove.
it would be nice if someone also has a linux and mac version of this …

i have used this snippet successfully since v0.05 with a little bit of OF-hackery but now it seems to integrate better with v0.06
since you can give the window a title.

USAGE:

  
  
int main( )  
{  
    ofAppGlutWindow window;  
    ofSetupOpenGL(&window, 1600,1200, OF_WINDOW);  
    window.setWindowTitle("mywindow");  
  
#ifdef WIN32  
    HWND hwnd = ::FindWindowA(0, "mywindow"); //NOTE, the windowtitle is crucial in order to find the handle, so you have to set it before!!!!  
    if (hwnd != NULL)  
    {  
        bool winStyleChanged = FALSE;  
        winStyleChanged = ModifyWindowStyle(hwnd, 0, WS_BORDER | WS_THICKFRAME | WS_CAPTION, FALSE);   //undecorate  
        //winStyleChanged = ModifyWindowStyle(hwnd, WS_BORDER | WS_THICKFRAME | WS_CAPTION, 0, FALSE);    //decorate  
        assert(TRUE == winStyleChanged);  
        ::SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);    //NOTE: repaint glutwindow to update style  
     }  
     else  
     {  
        printf("[WARNING] could NOT find window, title might be wrong\n");  
     }  
#endif  
  
    ofRunApp(new testApp());	  
}  
  

UTILITY-FUNCTION

  
  
#ifdef WIN32  
#include <windows.h>  
  
static bool ModifyWindowStyle(HWND hWnd, DWORD dwAdd, DWORD dwRemove, BOOL bEx)  
{  
   ::SetLastError(0);  
  
   DWORD dwStyle    = ::GetWindowLong(hWnd, (bEx ? GWL_EXSTYLE : GWL_STYLE));  
   DWORD dwNewStyle = (dwStyle & (~dwRemove)) | dwAdd;  
   ::SetWindowLong(hWnd, (bEx ? GWL_EXSTYLE : GWL_STYLE), dwNewStyle);  
  
   ::SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW | SWP_FRAMECHANGED);  
  
   //NOTE: this is necessary for updating visuals!!!  
   ::UpdateWindow(hWnd);  
   ::ShowWindow(hWnd, SW_SHOW);    //SW_SHOWNORMAL, SW_SHOWNA  
   ::SetFocus(hWnd);  
  
   return (::GetLastError() == 0);  
}  
#endif  
  

*hth*
didi