// Newton Line for Scriptographer
// version 20110908
// written by xoi (http://xoihazard.com)

tool.eventInterval = 1000 / 100;

var values = {
	lines: 1,
	mass: 30,
	gravity: 1,
	pressOn: true,
	pressGrav: 0.8,
	pressFric: 0.2,
	timescale: 0.2,
	friction: 0.02,
	rough: 5,
	drawAccel: true,
	optimize: false
};

var components = {
	r1: {
		label: 'Physical Variables', type: 'ruler'
	},
	mass: {
		type: 'slider', label: 'Mass', range: [1, 100]
	},
	friction: {
		type: 'slider', label: 'Friction', range: [0, 0.1]
	},
	timescale: {
		type: 'slider', label: 'Speed of Time', range: [0.01, 1]
	},
	r2: {
		label: 'Tablet Pressure', type: 'ruler'
	},
	pressOn: {
		type: 'checkbox', label: 'Pressure'
	},
	pressGrav: {
		type: 'slider', label: 'Gravity Variation', range: [0, 1]
	},
	pressFric: {
		type: 'slider', label: 'Friction (Decrease)', range: [0, 1]
	},
	r3: {
		label: 'Path Options', type: 'ruler'
	},
	rough: {
		type: 'slider', label: 'Rough', range: [0.1, 100]
	},
	optimize: {
		label: 'Optimize', type: 'checkbox'
	},
	credits: {
		type: 'text', value: 'xoihazard 20110908'
	}
};

var palette = new Palette('Newton Curve', components, values);

var newton = new Array(values.lines);

function onMouseDown(event) {
	for (i=0; i<newton.length; i++) {
		newton[i] = new nL(event, event.point);
	}
}

function onMouseDrag(event) {
	for (i=0; i<newton.length; i++) {
		newton[i].draw(event.point);
	}
}

function onMouseUp(event) {
	for (i=0; i<newton.length; i++) {
		newton[i].finish(values.optimize);
	}
}

function nL(event, center) {
	this.event = event;
	this.velocity = new Point(0, 0);
	this.lastPosition = center;
	this.path = new Path();
	this.path.add(this.lastPosition);
}

nL.prototype.draw = function(center) {
	var gravity, accel, position, friction, pressure;

	if (values.pressOn) {
		pressure = this.event.pressure;
	} else {
		pressure = 0.5;
	}
	friction = 1 - (values.friction - (values.friction * pressure * values.pressFric));
	gravity = center - this.lastPosition;
	gravity = gravity * (values.gravity - (values.gravity * ((-1+2*(1-pressure)) * values.pressGrav)));
	accel = gravity / values.mass;
	this.velocity = this.velocity * friction + accel * values.timescale;
	position = this.lastPosition + this.velocity;

	if (this.path.segments.last.point.getDistance(this.lastPosition) > values.rough) {
		this.path.add(position);
	}

	this.lastPosition = position;
}

nL.prototype.finish = function(optimize) {
	if (optimize) {
		this.path.pointsToCurves();
	} else {
		this.path.smooth();
	}
}
