Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fill the area of intersection of two Circles in Pygame

Tags:

python

pygame

I am working on a pygame project and I encountered a problem. I have two circles A and B as shown below. Which are overlapped Now I want to fill only some part of the circle which is common to both circles. Is there any way to achieve that?

I know I can fill circle B with red colour and circle A with white, but there is a certain area and circle A goes outside that area. So I cannot implement that.

The image of circles and filled position is mentioned in this image: enter image description here

like image 595
Bimal Timilsina Avatar asked Jul 23 '20 16:07

Bimal Timilsina


People also ask

How do you find the intersection area of two circles?

We can see that when the distance measure d is zero, the intersection area is π r 2 \pi r^2 πr2 with r being the smaller radius of both circles. If d is greater than the sum of both radii, the area of intersection is zero.

How do you code a circle in Pygame?

To draw a circle in your pygame project you can use draw. circle() function. The entire approach is the same as above only the function and parameters are changed accordingly.

How do you draw a curved line in Pygame?

A curved line in pygame can be as simple as using the pygame. draw. circle(surface,color,center,radius) and cropping part or most of it away. You can use trig functions to plot a curve, ect.

How to draw a circle in Pygame?

To draw a circle in your pygame project you can use draw.circle () function. The entire approach is the same as above only the function and parameters are changed accordingly. surface :- Here we can pass the surface on which we want to draw our circle. In the above example, we created a surface object named ‘window’.

How to create a rectangle in Pygame?

Now, Create the surface object of a specific dimension using the display.set_mode () method of pygame. Fill the background of the surface object with white color using the fill () function of pygame. Create a rectangle using the draw.rect () method of pygame. Update the Surface object. Example 1: Drawing outlined rectangle using pygame.

How to find the area of intersection between two circles?

Your task is to complete the function intersectionArea () which takes the coordinates of the centers as well as the radii (X1, Y1, R1, X2, Y2, R2) as input parameters and returns the area of intersection of the two circles.

How can I find the intersection of two lines in Python?

Alternatively, you can just extract four functions ( slope (), y_intercept (), intersect () & segment_intersect ()) and use them as you see fit. The function intersect ( line1, line2 ) tries to compute the intersection of line1 and line2; it includes a primitive sort of guard against numeric overflow, and returns a point (a tuple (x,y)).


Video Answer


2 Answers

Create 2 pygame.Surface objects with per pixel alpha (pygame.SRCALPHA):

surf1 = pygame.Surface((500, 500), pygame.SRCALPHA)
surf2 = pygame.Surface((500, 500), pygame.SRCALPHA)

Define the center point and radius of the 2 circles:

pos1, rad1 = (250, 200), 100
pos2, rad2 = (250, 250), 80

Draw the circles on the 2 surfaces, with the same color:

pygame.draw.circle(surf1, (255, 0, 0, 255), pos1, rad1)
pygame.draw.circle(surf2, (255, 0, 0, 255), pos2, rad2)

Blend one surface on the other, using the blend mode pygame.BLEND_RGBA_MIN:

surf1.blit(surf2, (0, 0), special_flags = pygame.BLEND_RGBA_MIN)

At this point surf1 contains the intersection area of the 2 circles.

To get the outer section, another step is required. Blend surf1 on surf2, using the blend mode pygame.BLEND_RGBA_MIN:

surf2.blit(surf1, (0, 0), special_flags = pygame.BLEND_RGBA_SUB)

Now surf2 contains the the part of circle B which is left if circle A is subtracted:


Minimal example: repl.it/@Rabbid76/PyGame-CircleIntersection

import pygame

pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()

pos1, rad1 = (250, 200), 100
pos2, rad2 = (250, 250), 80

surf1 = pygame.Surface((500, 500), pygame.SRCALPHA)
surf2 = pygame.Surface((500, 500), pygame.SRCALPHA)

pygame.draw.circle(surf1, (255, 0, 0, 255), pos1, rad1)
pygame.draw.circle(surf2, (255, 0, 0, 255), pos2, rad2)

surf1.blit(surf2, (0, 0), special_flags = pygame.BLEND_RGBA_MIN)
surf2.blit(surf1, (0, 0), special_flags = pygame.BLEND_RGBA_SUB)

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN:
            print(pygame.key.name(event.key))
 
    window.fill((255, 255, 255))

    window.blit(surf2, (0, 0))     
    pygame.draw.circle(window, (128, 128, 128), pos1, rad1+1, 3)
    pygame.draw.circle(window, (128, 128, 128), pos2, rad2+1, 3)

    pygame.display.flip()
like image 72
Rabbid76 Avatar answered Oct 22 '22 08:10

Rabbid76


I couldn't find a way to do it with pygame functions, so I made a quick demo on how to do it yourself here:

import pygame
import math
import time

# Screen dimensions
WIDTH = 600
HEIGHT = 400

# Circle and screen colours
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)

# Circle data
BIGGER_POS = (300, 150)
SMALLER_POS = (300, 220)
BIGGER_RADIUS = 130
SMALLER_RADIUS = 100
BIGGER_COLOUR = GREEN
SMALLER_COLOUR = BLUE
INTERSECTION_COLOUR = RED


def prepare_screen():
    """
    Create the initial screen.
    """
    pygame.init()
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    screen.fill(WHITE)
    return screen


def draw_circles(screen):
    """
    Draw the circles and wait to visually inspect what they look like.
    """
    bigger = pygame.draw.circle(screen, BIGGER_COLOUR, BIGGER_POS, BIGGER_RADIUS)
    smaller = pygame.draw.circle(screen, SMALLER_COLOUR, SMALLER_POS, SMALLER_RADIUS)
    pygame.display.update()
    time.sleep(3)
    return bigger, smaller


def calculate_distance(p1: tuple, p2: tuple):
    """
    Calculate distance between two points p1 and p2.
    """
    return math.sqrt(((p1[0] - p2[0])**2) + ((p1[1] - p2[1])**2))


def draw_intersection(screen, bigger, smaller):
    """
    Animation to mark intersecting points with red.
    
    Ideally this should only go through colliding points, but I'm lazy and made it iterate through all pixels
    instead.
    """
    for x in range(WIDTH):
        for y in range(HEIGHT):
            print("Checking point", x, y)
            
            # A point is in the intersection if it's within the radius-es of both circles
            if calculate_distance(bigger.center, (x, y)) <= BIGGER_RADIUS and \
                    calculate_distance(smaller.center, (x, y)) <= SMALLER_RADIUS:
                screen.set_at((x, y), INTERSECTION_COLOUR)
                pygame.display.update()


# Get screen to draw on
screen = prepare_screen()

# Draw some initial circles
bigger, smaller = draw_circles(screen)

# Draw the intersection
draw_intersection(screen, bigger, smaller)

# Finally sleep some to allow visual inspection, and quit
time.sleep(3)
pygame.quit()

Feel free to adjust as needed - note that various places can be optimised, made more readable etc.

Result:

Result of the code above

Let me know if anything's unclear.

like image 23
Kacper Floriański Avatar answered Oct 22 '22 08:10

Kacper Floriański