We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
Page Index Toggle Pages: 1
rings (Read 2965 times)
rings
Sep 29th, 2005, 3:51pm
 
hi all,

I'm looking for the best way to draw rings. The only way I can think of right now is to draw a circle and then at the same location a second circle with a smaller diameter and with a fill matching the background. This results in a ring-shape, but feels fake.

When two or more rings intersect only the outline of the resulting shape should be drawn. But to manage that, I have to draw a first "layer" of circles and then draw the second "layer" of circles over them at the corresponding locations. Wrong, wrong,wrong.

I wrote a little sketch to illustrate what I mean:

Code:


int n=74;
int border=2;

float[] rads = new float[n];

size(800,400);
background(0);

ellipseMode(CENTER_RADIUS);
noStroke();
smooth();

//first layer

n=0;
for(int i=30; i<width-30; i=i+10) {

float rad=random(4, 20);
rads[n] = rad;
fill(255);
ellipse(i, height/2, rad+border, rad+border);
n++;
}

//second layer

n=0;
for(int i=30; i<width-30; i=i+10) {

float rad = rads[n];
rads[n] = rad;
fill(0);
ellipse(i, height/2, rad, rad);
n++;
}



I'm guessing there must be a more elegant way to solve this problem. Anyone have a different approach? And what about ring-segments? Shurely you don't draw a ring and the lay a rectangle over a quarter of it to draw a 270°-ring-segment? Can I construct the segment with beziers?

cheers,
Greg


Re: rings
Reply #1 - Sep 29th, 2005, 4:16pm
 
you could use polygons to create the ring...

e.g.

Code:

void drawRing(int x, int y, float w1, float w2, int segments)
{
// w1 == outer radius, w2 == inner radius.
float deltaA=(1.0/(float)segments)*TWO_PI;
beginShape(QUADS);
for(int i=0;i<segments;i++)
{
vertex(x+w1*cos(i*deltaA),y+w1*sin(i*deltaA));
vertex(x+w2*cos(i*deltaA),y+w2*sin(i*deltaA));
vertex(x+w2*cos((i+1)*deltaA),y+w2*sin((i+1)*deltaA));
vertex(x+w1*cos((i+1)*deltaA),y+w1*sin((i+1)*deltaA));
}
endShape();
}


you can try varying the number of segments, depending how smooth you want the ring to be, 8 will look octagonal, 32 will look pretty smooth.
Re: rings
Reply #2 - Sep 29th, 2005, 9:40pm
 
Yeah, that's more like a ring with a real hole in the middle. But it uses much more cpu-power. I also can't see how to calculate the outline from overlapping rings.

Isn't it possible to calculate the intersection-points of any overlapping shapes and draw an outline with those? I'm guessing this will become insanely complicated, especially if the single elements are moving.



Re: rings
Reply #3 - Sep 29th, 2005, 10:10pm
 
It's possible, but it probably involves a fair bit of trigenometry and other maths I think.

I must admit that I king of skimmed your post and failed to see the multi-riug part.

To be honest, the drawing all of one layer, than all of the other, whilst hacky, is probably the easiest way to get the correct end image.

I can think of another way of going about drawing the rings to get the result you want, but it's a fairly odd pixel-centric way.

That would be, for each pixel on screen, work out the distance to all of your ring-centres, then for each ring-centre, work out if the pixel is in the middle part, in the ring, or completely outside, then if the pixel is only outside, it's not coloured, if it's only outside or in the ring, it's coloured, and if it's inside any, it's left. Thoguh this will be slow, and produce exactly the same result as the ellipse(..) method, and I only include it here, as an alternat way of lookign at the problem.
Re: rings
Reply #4 - Sep 29th, 2005, 10:12pm
 
How about increasing strokeWidth() and using arc():

http://www.processing.org/reference/arc_.html

It would take some mathmatical jiggering to calculate where the circles intersect, but once you have those angles you could just draw the arcs up to the intersects.

http://mathworld.wolfram.com/Circle-CircleIntersection.html

Would that work?
Re: rings
Reply #5 - Sep 29th, 2005, 11:54pm
 
I see arc() working with two circles. I'll have to try at that one after I get a hang of the trigonometry involved.

But as soon as there are three or more circles involved it'll get a lot more complicated. Imagine three circles, the one in the middle, slightly overlapped left and right by the others. Now we need two arcs to describe the outline-segments for the middle circle. Tricky.

I had a go at the "layer"-solution:

Code:


int MAX=100;
// declare array of positions
float[] myxlocs = new float[MAX];
float[] myylocs = new float[MAX];

Ring1[] myRings1 = new Ring1[MAX];
Ring2[] myRings2 = new Ring2[MAX];
Ring3[] myRings3 = new Ring3[MAX];

void setup() {
size(500,500);
// fill array with locations
for(int i=0; i<MAX; i++) {
myxlocs[i]=random(width);
myylocs[i]=random(height);
}

for (int i = 0; i < MAX; i++) {
float tempxp = random(width);
float tempyp = random(height);
float tempxv = random(1,1.5);
float tempyv = random(1,1.5);
myRings1[i] = new Ring1(tempxp, tempyp, tempxv, tempyv);
myRings2[i] = new Ring2(tempxp, tempyp, tempxv, tempyv);
myRings3[i] = new Ring3(tempxp, tempyp, tempxv, tempyv);
}
smooth();
}

void draw() {
background(255);

for (int i=0; i<MAX; i++) {
myRings3[i].drive();
myRings3[i].draw();
}

for (int i=0; i<MAX; i++) {
myRings2[i].drive();
myRings2[i].draw();
}

for (int i=0; i<MAX; i++) {
myRings1[i].drive();
myRings1[i].draw();
}
}

class Ring1 {

float xpos;
float ypos;
float xvel;
float yvel;
float xsize;
float ysize;

Ring1(float xp, float yp, float velx, float vely) {

xpos = xp;
ypos = yp;
xvel = velx;
yvel = vely;

xsize = 20;
ysize = xsize;
}

void draw () {
ellipseMode(CENTER);
// fill(0,100,255);
fill(0,255,0);
noStroke();
ellipse(xpos, ypos, xsize, ysize);
}

void drive () {
xpos = xpos + xvel;
if (xpos > width + xsize) {
xpos = -xsize-20;
}
ypos = ypos + yvel;
if (ypos > width + ysize) {
ypos = -ysize-20;
}
}
}

class Ring2 {

float xpos;
float ypos;
float xvel;
float yvel;
float xsize;
float ysize;

Ring2(float xp, float yp, float velx, float vely) {
xpos = xp;
ypos = yp;
xvel = velx;
yvel = vely;

xsize = 30;
ysize = xsize;
}

void draw () {
ellipseMode(CENTER);
fill(255,255,255);
noStroke();
ellipse(xpos, ypos, xsize, ysize);
}

void drive () {
xpos = xpos + xvel;
if (xpos > width + xsize) {
xpos = -xsize+20-20;
}
ypos = ypos + yvel;
if (ypos > width + ysize) {
ypos = -ysize+20-20;
}
}

}

class Ring3 {

float xpos;
float ypos;
float xvel;
float yvel;
float xsize;
float ysize;

Ring3(float xp, float yp, float velx, float vely) {
xpos = xp;
ypos = yp;
xvel = velx;
yvel = vely;

xsize = 40;
ysize = xsize;
}

void draw () {
ellipseMode(CENTER);
fill(0,150,200);
noStroke();
ellipse(xpos, ypos, xsize, ysize);
}

void drive () {
xpos = xpos + xvel;
if (xpos > width + xsize) {
xpos = -xsize+40-20;
}
ypos = ypos + yvel;
if (ypos > width + ysize) {
ypos = -ysize+40-20;
}
}
}



It actually works good enough. It's still very unelegant to use three classes, but I didn't see another way to seperate all the layers from each other. Whats your take?
Re: rings
Reply #6 - Sep 30th, 2005, 2:42am
 
Yup, layers is a lot simpler than effing about with a load of old wolfram. What you're doing is pretty similar to what Jared Tarbell has done here:

http://www.levitated.net/daily/levOilyStratum.html

Started to explain the shorter code then thought I'd put it into code (and for some reason it took me ages to figure out the simple method of setting the distance according to layer on respawn):
Code:

int rings = 100;
int layers = 3;
Ring [][] ring;
void setup() {
size(500,500);
ring = new Ring[layers][rings];
for (int i = 0; i < ring[0].length; i++) {
float tempxp = random(width);
float tempyp = random(height);
float tempxv = random(1,1.5);
float tempyv = random(1,1.5);
for(int j = 0; j < ring.length; j++){
ring[j][i] = new Ring(tempxp, tempyp, tempxv, tempyv, 20+(j*10), j);
}
}
smooth();
}

void draw() {
background(255);
for(int i = ring.length-1; i > -1; i--){
for(int j = 0; j < ring[i].length; j++){
ring[i][j].drive();
ring[i][j].draw();
}
}
}

class Ring{
float xpos,ypos,xvel,yvel,xsize,ysize,layer;
Ring(float xp, float yp, float velx, float vely, float size, float layer) {
xpos = xp;
ypos = yp;
xvel = velx;
yvel = vely;
xsize = size;
ysize = xsize;
this.layer = layer;
}
void draw () {
ellipseMode(CENTER);
// fill(0,100,255);
fill(layer*10,255-layer*10,0);
noStroke();
ellipse(xpos, ypos, xsize, ysize);
}
void drive () {
xpos = xpos + xvel;
if (xpos > width + xsize) {
xpos = -xsize-20+(layer*20);
}
ypos = ypos + yvel;
if (ypos > width + ysize) {
ypos = -ysize-20+(layer*20);
}
}
}

Grin
Re: rings
Reply #7 - Sep 30th, 2005, 1:05pm
 
Now that's what I call cleaning up. Goes to show that I've still some way to go getting my coding together.

I actually remember seeing the levitated-piece, but without checking on the details. Seems like it's quite allright to fake it every now and then.
Re: rings
Reply #8 - Oct 15th, 2005, 5:31pm
 
other ways of doing it may be: masks, blending modes, or even consecutive concentric circles to give the impression of width
Page Index Toggle Pages: 1