From: Gavin Kistner Date: 2006-09-10T00:44:47+09:00 Subject: Re: Overlapping circles - modelling living populations ------_=_NextPart_001_01C6D426.DC47EB36 Content-Type: text/plain; charset="Windows-1252" Content-Transfer-Encoding: quoted-printable 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 =3D Math.sqrt( ( cx - other_circle.cx ) ** 2 + ( cy - other_circle.cy ) ** 2 ) intersects =3D center_distance < ( r + other_circle.r ) =20 # Save the result on both circles =20 other_circle.overlaps[ self ] =3D intersects self.overlaps[ other_circle ] =3D intersects end =20 def overlaps # Make sure we have a hash to save a set of overlappers @overlapping_circles ||=3D {} end =20 # 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 ||=3D {} @overlapping_circles.select{ |circle,status| status =3D=3D true }.map{ |circle,status| circle } end end # Create/manage your populations populations =3D [] 20.times{ # Randomly add populations x =3D rand 800 + 100 y =3D rand 800 + 100 radius =3D 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 =3D 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 =3D SVG::Group.new{ self.style =3D SVG::Style.new( :fill =3D> '#ffe', :stroke =3D> 'blue', :stroke_width =3D> 1.5 ) } # Need opacity per element, not on the group low_opacity =3D SVG::Style.new( :opacity =3D> 0.6 ) # Override style for circles that overlap olap_style =3D SVG::Style.new( :fill=3D>'#ff9', :stroke=3D>'red', = :opacity=3D>0.4 ) populations.each{ |circle| if circle.overlapping_list.empty? circle.style =3D low_opacity else circle.style =3D 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 ------_=_NextPart_001_01C6D426.DC47EB36--