Re: Overlapping circles - modelling living populations

Here’s a slightly better version that uses the overlapping status of a
circle to change its color. (It doesn’t do anything with pairs of
circles, though that’d also be easy…you just have to know how you’d
want to visualize it.)

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 100 + 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

0.step( 1000, 20 ){ |i|
svg << SVG::Line.new( i, 0, i, 1000 )
svg << SVG::Line.new( 0, i, 1000, i )
}

Make all circles have a common style

svg << g = SVG::Group.new{
self.style = SVG::Style.new(
:fill => ‘#ffe’, :stroke => ‘blue’, :stroke_width => 1.5
)
}

Need opacity per element, not on the group

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

Override style for circles that overlap

olap_style = SVG::Style.new( :fill=>’#ff9’, :stroke=>‘red’,
:opacity=>0.4 )

populations.each{ |circle|
if circle.overlapping_list.empty?
circle.style = low_opacity
else
circle.style = olap_style
end
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

Gavin,

On Sun, 2006-09-10 at 00:44 +0900, Gavin K. wrote:

end
intersects = center_distance < ( r + other_circle.r )

end

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

Need opacity per element, not on the group

end
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

Many thanks for that! I will have to go over this in detail to
understand what is happening but it looks nice! A couple of things:

  1. There seems to be some doubt about the survival of SVG . .

  2. Opera supports SVG natively! (which seems to go against the first
    point)

Regards,

Phil.

Philip R.

Pricom Pty Limited (ACN 003 252 275 ABN 91 003 252 275)
GPO Box 3411
Sydney NSW 2001
Australia
Mobile: +61:(0)411-185-652
Fax: +61:(0)2-8221-9599
E-mail: [email protected]