Overlapping Circles
Splizard

I am playing around with the primitives library and I am wondering if there is any way to draw circles of different colours without them overlapping each other..?

like this:
lens1.png
(Imagine the circles are different colors)
rather than this:
{"name":"40030d1336416221-how-find-distance-between-two-overlapping-circles-eclipse.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/e\/9e279ea0685bef975d4800699990efea.jpg","w":419,"h":290,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/e\/9e279ea0685bef975d4800699990efea"}40030d1336416221-how-find-distance-between-two-overlapping-circles-eclipse.jpg
For example to have the circles cut at line 'C' so they don't overlap... ???

Is there a simple efficient way to go about this or should I stick to the same colour to give the illusion of not overlapping?

jmasterx

Maybe this could be done with the stencil buffer

http://en.wikipedia.org/wiki/Stencil_buffer

Or perhaps when drawing the second circle you can use clipping rect.

Yeah, clipping rect can do this.

Splizard

It would be nice if I could do it without explicitly calling OpenGL :)

Thanks, but the clipping rectangle doesn't seem to work at any angle...

al_set_clipping_rectangle(int x, int y, int width, int height)

So I guess I would then need to rotate the coordinates to achieve this at different angles?

beoran

The way to do this could be to calculate the 2 arcs using al_calculate_line, and then close the line piece by using al_calculate_line, then finally use al_draw_prim to draw the resulting figure.

https://www.allegro.cc/manual/5/al_calculate_arc

You can also use Allegro's transformations to translate and rotate coordinates.

Pho75_

i would convert the 2 circles into 2 arrays of raster lines
(same as you would for drawing triangles).
each raster has:
x1, -left side of circle
x2, -right side of circle
y, -y coord of raster line
midx -intersection coord (to be calculated)

so you can draw an entire circle by stepping through the array.

for y= y1 to y2
draw_line (x1, y, x2, y, color);

NOTE: if you have an optimized draw_hline function,
this will be faster than a generic draw_line (for software rendering).
For opengl it might not matter.

1.
sort the circles so circle1 is on the left and circle2 on the right

2.
loop thru the raster array for each circle and calculate the intersection x-coord.
To get the even split down the middle, just average the overlapping
x coordinates.

do a bounding box check on the y coordinate first.
for each raster line (y coord) from circle1 that intersects circle2
then do bounds checking to determine if they intersect for x coordinates too

if (intersects)
midx= the average of circle1_x2 and circle2_x1

3. draw each circle by looping through the raster lines.

circle1:
for y= y1 to y2
draw_line (circle1_x1, y, midx-1, y, color)

circle2:
for y= y1 to y2
draw_line (midx, y, circle2_x2, y, color)

obviously, if both circles aren't on the same y coordinate u have to do
the relative y-coord math when comparing the raster lines.

This should work for circles of different sizes too, i think.

this algorithm probably only works as long as 1 circle is not completely inside
the other circle1. You'll have to do the math to prevent that case from happening.

Edgar Reynaldo
Splizard said:

Thanks, but the clipping rectangle doesn't seem to work at any angle...

al_set_clipping_rectangle(int x, int y, int width, int height)

It works for me in this simple example :

#SelectExpand
1 2 3 4#include "allegro5/allegro.h" 5#include "allegro5/allegro_primitives.h" 6#include "allegro5/allegro_image.h" 7 8int main(int argc , char** argv) { 9 10 11 if (!al_init()) {return 1;} 12 if (!al_init_primitives_addon()) {return 2;} 13 if (!al_init_image_addon()) {return 3;} 14 15 al_set_new_display_flags(ALLEGRO_WINDOWED); 16 ALLEGRO_DISPLAY* display = al_create_display(300,200); 17 18 al_clear_to_color(al_map_rgb(0,0,0)); 19 20 al_set_clipping_rectangle(0,0,150,200); 21 al_draw_filled_circle(100,100,100,al_map_rgb(0,255,0)); 22 al_set_clipping_rectangle(150,0,150,200); 23 al_draw_filled_circle(200,100,100,al_map_rgb(0,0,255)); 24 25 al_save_bitmap("primclip.png" , al_get_backbuffer(display)); 26 27 al_flip_display(); 28 29 al_rest(3.0); 30 31 return 0; 32}

{"name":"608871","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/f\/1f0a8f0ef5d0ec4a6895038594a8e6af.png","w":300,"h":200,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/f\/1f0a8f0ef5d0ec4a6895038594a8e6af"}608871

Though to get rotated 'molecules' you would need to use a subbitmap to draw your circles on horizontally and then use the transformation matrix to draw it rotated on screen. The clipping gets applied after the transformation as far as I know.

Gideon Weems

The Master has a great post on this.

Splizard

@Edgar Reynaldo
It would be nice if you could set an arbitrary clipping line at any angle :-/
The need is for this to work at any angle, if you moved one of the circles around it would always merge with the other circle no matter which way they intersect.
Creating subitmaps seems maybe inefficient? If your dealing with large amounts of circles or "Molecules".

Out of the solutions above which would theoretically be the most speed efficient way?

Arthur Kalliokoski

I'd think drawing actual lit 3D intersecting spheres would be easiest in the long run.

Thread #614565. Printed from Allegro.cc