// Constraint class for Verlet physics engine
// by Andreas Blixt <andreasblixt@msn.com> 2007
// Free for use. Please include this header.

Constraint = function (atom1, atom2, amplitude, frequency, step) {
	// Make sure a from-atom was passed.
	if (!(atom1 instanceof Atom)) throw "First argument must be an instance of Atom.";

	// Make sure a to-atom was passed.
	if (!(atom2 instanceof Atom)) throw "Second argument must be an instance of Atom.";

	// Store a reference to the group of the first atom, which this constraint will belong to.
	this.Group = atom1.Group;

	// Store references to the atoms which this contraint constrains.
	this.Atom1 = atom1;
	this.Atom2 = atom2;

	// Calculate the rest length of this constraint.
	var dx = atom2.CurrentX - atom1.CurrentX;
	var dy = atom2.CurrentY - atom1.CurrentY;
	this.Length = Math.sqrt(dx * dx + dy * dy);

	// Set motoric properties.
	this.Amplitude = parseFloat(amplitude);
	this.Frequency = parseFloat(frequency) * Math.PI * 2;
	this.Step = parseFloat(step) * Math.PI * 2;
	if (isNaN(this.Step)) this.Step = 0.0;
	this.BaseLength = isNaN(this.Amplitude) || isNaN(this.Frequency) || isNaN(this.Step) ? this.Length : this.Length - Math.sin(this.Step) * this.Amplitude;

	// Get a unique ID for this constraint.
	var idCounter = 1;
	while (this.Group.World.GetByID(this.ID = "constraint" + idCounter++));

	// Add this constraint to the specified group.
	this.Group.Constraints.push(this);

	// Add this constraint to the global list of objects.
	this.Group.World.All.push(this);
};

Constraint.prototype = {
	// A unique string identifying this particular constraint.
	ID: "",

	// A reference to the group which this constraint belongs to.
	Group: null,

	// The atoms which this constraint constrains.
	Atom1: null, Atom2: null,

	// The length at which this constraint is at rest.
	BaseLength: NaN, Length: NaN,

	// Motoric properties
	Amplitude: NaN, Frequency: NaN, Step: NaN,

	// Removes this constraint.
	Remove: function () {
		for (var i in this.Group.Constraints)
			if (this.Group.Constraints[i] === this) this.Group.Constraints.splice(i, 1);
		for (var i in this.Group.World.All)
			if (this.Group.World.All[i] === this) this.Group.World.All.splice(i, 1);
	}
};