ofGraphics::ofCircleSlice() (aka a function to draw Pac-Man)

Ok, so I needed to be able to draw a wedge or slice of a circle, and ended up writing this function to do it.

I’ve tested it on oF 0.06 and it works in ofNoFill() or ofFill() mode. There seems to be a slight issue with it not drawing all the way to the highAngle (like it’s a few degrees off or something) which I am not sure how to fix properly, perhaps someone can have a look?

For parameters, it lets you specify the standard x, y, radius, and also a lowAngle and highAngle to specify the slice you want to draw.
bool closed flags if it should be a LINE_LOOP or LINE_STRIP in ofNoFill() mode.
bool radians just specifies if the angles you’re passing are in radians (true) or degrees (false).

ofGraphics.h

  
  
void ofCircleSlice(float x,float y, float radius, float lowAngle, float highAngle, bool closed=false, bool radians=false);  
  

ofGraphics.cpp

  
  
//----------------------------------------------------------  
void ofCircleSlice(float x,float y, float radius, float lowAngle, float highAngle, bool closed, bool radians){  
	if (!bSetupCircle) setupCircle();  
	  
	// use smoothness, if requested:  
	if (bSmoothHinted && drawMode == OF_OUTLINE) startSmoothing();  
	  
	bool angleWrap = (lowAngle > highAngle); // are we doing the 0/360 wrap?  
	  
	if(!radians){  
		lowAngle = ofDegToRad(lowAngle);  
		highAngle = ofDegToRad(highAngle);  
	}  
	  
	int res = numCirclePts;  
	float angle = lowAngle;  
	float angleRange = ((!angleWrap)?(highAngle - lowAngle):(M_TWO_PI - lowAngle + highAngle));  
	float angleAdder = angleRange / (float)res;  
	int k = 0;  
	for (int i = 0; i < numCirclePts; i++){  
		circlePtsScaled[k] = x + cos(angle) * radius;  
		circlePtsScaled[k+1] = y - sin(angle) * radius;  
		angle += angleAdder;  
		k+=2;  
	}  
	  
	// we draw the circle points ourself (vs. glDrawArrays) because it allows us to draw the center point, and have the triangles fan around it  
	k = 0;  
	glBegin((drawMode == OF_FILLED) ? GL_TRIANGLE_FAN : (closed?GL_LINE_LOOP:GL_LINE_STRIP));  
	glVertex2f(x, y); // center vertex  
	  
	// now all the points around the circumference  
	for (int i = 0; i < numCirclePts; i++){  
		glVertex2f(circlePtsScaled[k], circlePtsScaled[k+1]);  
		k+=2;  
	}  
	glEnd();  
	  
	// back to normal, if smoothness is on  
	if (bSmoothHinted && drawMode == OF_OUTLINE) endSmoothing();  
}  
  

Enjoy!

:slight_smile: ni ce code, help so much (^-^)

THX

thank you for sharing this code. it is quite usefull.
i have been using it, and if you use ofNoFill() and closed as false, it draws a line from the center point to the start of the arc.
is there any way i can bypass the drawing of that line?
i come from processing, and it had an arc function, which i liked to use, and openFrameworks lacks this function (yours being the most similar)

Sorry for being a noob, but does anybody know how I would add ofCircleSlice() to ofGraphics in OF 0.61 where I link against the OF library instead of having all the files in my project?

Hi!

I needed exactly such function, thanx plong0!

To bypass drawing of the center_to_radius line in ofNoFill mode (as ilikesushi requested) I modified the line which says

  
   glVertex2f(x, y); // center vertex  
  

to:

  
   if (closed || (drawMode == OF_FILLED)) glVertex2f(x, y); // center vertex  
  
  

edit: added " || (drawMode == OF_FILLED)" to new code, now it really works like charm!

cheers

I’m trying to use ofCircleSlice() on an iphone application, but since you can’t use glBegin, glEnd, or glVertex2f how could we best adapt this for openGL ES?

Looks like i’ll answer my own question :wink:

  
  
//----------------------------------------------------------  
void ofCircleSlice(float x,float y, float radius, float lowAngle, float highAngle, bool closed, bool radians){  
	if (!bSetupCircle) setupCircle();  
	  
	// use smoothness, if requested:  
	if (bSmoothHinted && drawMode == OF_OUTLINE) startSmoothing();  
	  
	bool angleWrap = (lowAngle > highAngle); // are we doing the 0/360 wrap?  
	  
	if(!radians){  
		lowAngle = ofDegToRad(lowAngle);  
		highAngle = ofDegToRad(highAngle);  
	}  
	  
	int res = numCirclePts;  
	float angle = lowAngle;  
	float angleRange = ((!angleWrap)?(highAngle - lowAngle):(M_TWO_PI - lowAngle + highAngle));  
	float angleAdder = angleRange / (float)res;  
	int k = 0;  
	for (int i = 0; i < numCirclePts; i++){  
		circlePtsScaled[k] = x + cos(angle) * radius;  
		circlePtsScaled[k+1] = y - sin(angle) * radius;  
		angle += angleAdder;  
		k+=2;  
	}  
	  
	//initial points  
	circlePtsScaled[0] = x;  
	circlePtsScaled[1] = y;  
	k = 2;  
	// now all the points around the circumference  
	for (int i = 2; i < numCirclePts; i++){  
		circlePtsScaled[k] = circlePtsScaled[k];  
		circlePtsScaled[k+1] = circlePtsScaled[k+1];		  
		k+=2;  
	}  
	  
	glEnableClientState(GL_VERTEX_ARRAY);  
	glVertexPointer(2, GL_FLOAT, 0, &circlePtsScaled[0]);  
	glDrawArrays( (drawMode == OF_FILLED) ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, numCirclePts);  
	  
	  
	// back to normal, if smoothness is on  
	if (bSmoothHinted && drawMode == OF_OUTLINE) endSmoothing();  
}  
  
  
  

  
float angleAdder = angleRange / (float)res-1;    

should be…

  
float angleAdder = angleRange / (float)(res-1);  

Otherwise there will always be one segment not drawn!

Hi, I am trying to use the ofxMotionTracker wich uses these circleSlice classes but it seems that there is a whole lot of stuff undefined in the ofCircleSlice.cpp. (functions and var definitions) Am I missing something?

If anyone is still wondering about drawing “circle slices” or trying to get ofxMotionTracker working with the latest oF libs, look into ofPath::arc. This does essentially the same thing as ofCircleSlice.

So for example, to get this version of ofxMotionTracker working, you could change the contents of ofCircleSlice to something like this:

  
ofPath tArcPath;  
tArcPath.setArcResolution(360);  
tArcPath.arc(x, y, radius, radius, lowAngle, highAngle);  
tArcPath.draw();  

2 Likes

Thnx sudo_user, that was exactly what I needed !