From: Philip R. [mailto:[email protected]]

I have been thinking about how to use Ruby for modelling populations - I

want to use circles on a grid to represent the size of individual

populations and determine if there is dispersal between pairs of

populations by testing whether there is overlap with the two circles.

Here’s a solution using SVG, assuming you want to visualize the results.

It’s even easier rolling your own Circle class using matrix/Vector to

calculate

distances.

# http://downloads.sourceforge.jp/ruby-svg/2288/ruby-svg-1.0.3.tar.gz

require ‘svg/svg’

class Array

def each_unique_pair

self.each_with_index{ |a,i|

self[(i+1)…-1].each{ |b| yield a,b }

}

end

end

class SVG::Circle

# test (and save) result

def overlaps?( other_circle )

center_distance = Math.sqrt(

( cx - other_circle.cx ) ** 2 +

( cy - other_circle.cy ) ** 2

)

```
intersects = center_distance < ( r + other_circle.r )
# Save the result on both circles
other_circle.overlaps[ self ] = intersects
self.overlaps[ other_circle ] = intersects
end
def overlaps
# Make sure we have a hash to save a set of overlappers
@overlapping_circles ||= {}
end
# An array of all circles this one overlaps
def overlapping_list
# Make sure we have a hash to save a set of overlappers
@overlapping_circles ||= {}
@overlapping_circles.select{ |circle,status|
status == true
}.map{ |circle,status|
circle
}
end
```

end

# Create/manage your populations

populations = []

20.times{

# Randomly add populations

x = rand 800 + 100

y = rand 800 + 100

radius = rand 150 + 10

populations << SVG::Circle.new( x, y, radius )

}

# Make sure the overlapping list is valid

populations.each_unique_pair{ |a,b|

a.overlaps?( b )

}

# Make the picture

svg = SVG.new(‘100%’, ‘100%’, ‘0 0 1000 1000’)

# Your grid here…lots of SVG::Lines

0.step( 1000, 20 ){ |i|

svg << SVG::Line.new( i, 0, i, 1000 )

svg << SVG::Line.new( 0, i, 1000, i )

}

svg << g = SVG::Group.new{

self.style = SVG::Style.new(

:fill => ‘#ffc’, :stroke => ‘red’, :stroke_width => 1.5

)

}

low_opacity = SVG::Style.new( :opacity => 0.5 )

populations.each{ |circle|

circle.style = low_opacity

g << circle

}

File.open( ‘populations.svg’, ‘w’ ){ |file|

file << svg.to_s

}