require 'Vector'
require 'Particle'
require 'Euler'


class Newton

	attr_reader :distance2
	
	def initialize(particles)
		#
		# Array of particles.
		#
		@particles=particles
		#
		# Strategy object for doing the integration
		#
		@integrator=Euler.new
		#
		# Assoc array of assoc arrays of distances squared.
		# Distance squared between p1 and p2 is distance2[p1][p2]
		#
		@distance2={}
	end
	
	#
	# Compute the distnaces squared between all the particles.
	# d squared is used in serveral of the calculations, so we
	# compute and store it in one step.
	#
	def computeDistancesSquared
	
		#
		# First set up the table of distances squared
		#
		for p1 in @particles
			@distance2[p1]={}
		end
		
		for p1 in @particles
			row= @distance2[p1]
			for p2 in @particles
				if ( ! row.key?(p2) )
					row[p2] = (p2.pos - p1.pos).magnitude2
					@distance2[p2][p1] = row[p2]
				end
			end
		end
	end

	#
	# Compute the gravitation attraction of other on this particle.
	#
	def computeGravitationalForce( other )
		#
		# The delta position vector
		#
		deltaS = self.pos - other.pos
		#
		# Get the sq of the distance.
		#
		distance2 = deltaS.magnitude2
		#
		# Get the distance
		#
		distance = sqrt(distance2)
		#
		# Normalize the position vector
		#
		components = deltaS.scaleDiv(distance)
		#
		# Now compute the total force of gravity
		#
		g = 1.0 * self.mass * other.mass / d2
		#
		# Compute the components of the force
		#
		components.scaleMul!(g)

		return components
	end

end

p=[ Particle.new( 'one', 1, Vector3D.new( 0,0,0), Vector3D.new(0,0,0) ),
      Particle.new( 'two', 1, Vector3D.new( 1,0,0), Vector3D.new(0,0,0) ),
      Particle.new( 'Three', 1, Vector3D.new( 0,10,0), Vector3D.new(0,0,0) )
     ]

n = Newton.new(p)
n.computeDistancesSquared

d=n.distance2
for first in d.keys
	for second in d.keys
		print "p1: ", first, " p2: ", second, " " ,d[first][second], "\n"
	end
end
puts(n.distance2)

