------_extPart_001_01C6D425.8C856FBC
Content-Type: text/plain;
	charsetindows-1252"
Content-Transfer-Encoding: quoted-printable

From:	Philip Rhoades [mailto:phil / pricom.com.au]
> 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
}

# view in your favorite SVG viewer, like FF 1.5
# for an example, see http://phrogz.net/svg/populations.svg

------_extPart_001_01C6D425.8C856FBC--