Pushing cell agents

Hi,

I’m trying to make a Cell Division and Growth algorithm where cell agents are pushed right next to neighboring cell just after the division process. I’d like the final output to look like a circle packing.

However in my example sketch cells are pushed farther than their neighboring cell’s radii

How can I correct this behavior ?

def setup():
    global collection
    size(480, 360, P2D)
    smooth(8)
    
    collection = [Cell(PVector(width>>1, height>>1), 20)]

        
def draw():
    background(255)
    
    for c in collection:
        c.growth()
        c.interact()
        c.display()

    
class Cell(object):
    growthInterval = 10
    divisionInterval = 100
    
    def __init__(self, pos, rad):
        self.position = pos
        self.radius = rad
        self.time = 0
    
    def interact(self):
        for a in collection:
            if a is not self:
                d = PVector.dist(a.position, self.position)
                if d < a.radius + self.radius:
                    #gap = (a.radius + self.radius) - d

                    diff = PVector.sub(self.position, a.position)
                    diff.normalize()
                    diff.div(d)
                    a.position.sub(diff)           
                        
    def growth(self):
        self.time += 1
        if len(collection) < 100:

            if self.time > 0 and self.time%Cell.divisionInterval == 0:
                if random(1) > .5:
                    dir = PVector.random2D()
                    self.radius *= .5
                    child = Cell(self.position+dir, self.radius)
                    collection.append(child)
                    self.position.sub(dir)

            if self.time%Cell.growthInterval == 0:
                self.radius += .5
                
                                  
    def display(self):
        strokeWeight(3)
        point(self.position.x, self.position.y)
        noFill()
        strokeWeight(1)
        ellipse(self.position.x, self.position.y, self.radius, self.radius)
1 Like

So it seems I have to divide the radii by 2 (on the fourth line of the “interact” function) but it doesn’t make sense because I already did it on line 7 in the “growth” function.

If someone can find what’s going on.

Here:

diff = PVector.sub(self.position, a.position)
diff.normalize()
diff.div(d)
a.position.sub(diff)    

If you’re normalizing the vector, shouldn’t you multiply it by its radius instead? (Not divide it by the distance)

Hi Sarah,

I think that part (that I’m borrowing from Daniel Shiffman’s tutorial on boids) isn’t appropriate in this sketch and I shouldn’t be normalizing the the vectors’ distances in the first place. But you’re right in noting that I should do something with the radii at some point (but don’t know what exactely).

Here’s what I came up with instead:


def interact(self):
    for a in collection:
        if a is not self:

            #Distance between 2 vectors
            d = PVector.dist(self.position, a.position)

            #If that distance is smaller than the sum of the radii (+ strokeWeight)
            if d < (a.radius*.5 + self.radius*.5 + 1):

                #Compute gap distance
                gap = (a.radius*.5 + self.radius*.5 + 1) - d

                #Not sure what I'm doing here
                diff = PVector.sub(self.position, a.position)

                #Pushing the cell to the right distance (setting the magnitude to the sum of the radii)
                a.position.sub(diff.setMag(gap))

Still, I don’t understand why I have to divide the radii by 2 again. It shouldn’t be that way.

1 Like

I think you might be mixing the radius with the diameter of the circle. The radius should be half of the circles diameter so instead of
ellipse(self.position.x, self.position.y, self.radius, self.radius)
it should be
ellipse(self.position.x, self.position.y, self.radius*2, self.radius*2)

3 Likes

Of course… thank you Sarah.