var nb = this.negBleed.x
, v = this.canvasWidth = w + nb + this.posBleed.x;
- this.canvas[0].width = v;
this.canvas.css({
'width' : v+'px',
'margin-left' : (-nb)+'px'
});
+ this.canvas[0].width = v;
return this;
},
var nb = this.negBleed.y
, v = this.canvasHeight = h + nb + this.posBleed.y;
- this.canvas[0].height = v;
this.canvas.css({
'height' : v+'px',
'margin-top' : (-nb)+'px'
});
+ this.canvas[0].height = v;
return this;
},
$(function(){
$('<style />')
.text([
- '.portal.layer { position:absolute; z-index:1; top:0; left:0; }',
+ '.portal.layer { position:absolute; z-index:1; top:0; left:0; line-height:0; }',
'.portal.layer canvas { z-index:0; }'
].join('\n'))
.appendTo('head');
--- /dev/null
+/**
+ * A line.
+ */
+math.Line = new Y.Class('Line', math.Vec, {
+
+ init : function init(x1,y1, x2,y2, t){
+ this.t = 1/(t || 1);
+ this.x1 = x1; this.y1 = y1;
+ this.x2 = x2; this.y2 = y2;
+
+ var xdelta = x2-x1, ydelta = y2-y1
+ , m = this.slope = ydelta/xdelta
+ , yi = this.yint = -x1*m + y1
+ , xi = this.xint = -y1/m + x1
+ ;
+
+ this.pa = this.t*xdelta;
+ this.pb = this.t*ydelta
+ math.Vec.init.call(this, xdelta, ydelta);
+ },
+
+ pcalc : function parametric(t){
+ return new math.Vec( this.x1 + this.pa*t ,
+ this.y1 + this.pb*t );
+ },
+
+ calcY : function calcY(x){
+ return x*this.slope + this.yint;
+ },
+
+ calcX : function calcX(y){
+ return y/this.slope + this.xint;
+ },
+
+ toString : function toString(){
+ return 'Line('+this.x1+','+this.y1+', '+this.x2+','+this.y2+', slope='+this.slope+')';
+ }
+
+});
\ No newline at end of file
--- /dev/null
+math = {
+ clamp : function clamp(value, min, max) {
+ return Math.min(Math.max(value, min), max);
+ },
+
+ lerp : function lerp(x, a, b) {
+ return a + x*(b - a);
+ }
+};
\ No newline at end of file
--- /dev/null
+/**
+ * A 2-dimensional vector.
+ */
+math.Vec = new Y.Class('Vec', {
+
+ init : function init(x, y){
+ if ( Array.isArray(x) ) {
+ y = x[1];
+ x = x[0];
+ }
+
+ this.x = x;
+ this.y = y;
+ },
+
+ equals : function equals(b){
+ return (this.x === b.x) && (this.y === b.y);
+ },
+
+ clone : function clone(){
+ return new Vec(this.x, this.y);
+ },
+
+ scale : function scale(s){
+ this.x *= s;
+ this.y *= s;
+ return this;
+ },
+
+ invert : function invert(){
+ this.x = -this.x;
+ this.y = -this.y;
+ return this;
+ },
+
+ normalize : function normalize(){
+ return this.scale(1 / this.magnitude());
+ },
+
+ add : function add(b){
+ this.x += b.x;
+ this.y += b.y;
+ return this;
+ },
+
+ subtract : function subtract(b){
+ this.x -= b.x;
+ this.y -= b.y;
+ return this;
+ },
+
+ magnitude : function magnitude(){
+ return Math.sqrt(this.x*this.x + this.y*this.y);
+ },
+
+ sqMagnitude : function sqMagnitude(){
+ return this.x*this.x + this.y*this.y;
+ },
+
+ dot : function dot(b){
+ return this.x*b.x + this.y*b.y;
+ },
+
+ toString : function toString(){
+ return 'Vec('+this.x+','+this.y+')';
+ }
+
+});
+
+Y.extend(math.Vec, {
+ sum : function sum(a, b) {
+ return new Vec(a.x+b.x, a.y+b.y);
+ },
+
+ difference : function difference(a, b) {
+ return new Vec(a.x-b.x, a.y-b.y);
+ },
+
+ dot : function dot(a, b) {
+ return a.x*b.x + a.y*b.y;
+ },
+
+ lerp : function lerp(x, a, b) {
+ return new Vec( math.lerp(a.x, b.x, x),
+ math.lerp(a.y, b.y, x) );
+ },
+
+ reflect : function reflect(v, line){
+ return line.clone()
+ .scale(2 * v.dot(line) / line.dot(line))
+ .subtract(v);
+ }
+
+});
});
+Circle = new Y.Class('Circle', Shape, {
+ _cssClasses : 'portal layer shape circle',
+
+ init : function init(radius){
+ Layer.init.call(this);
+
+ var d = radius * 2;
+ this.radius = radius;
+ this.width(d).height(d)
+ .origin(radius,radius);
+ },
+
+ drawShape : function drawShape(ctx){
+ var r = this.radius;
+ ctx.arc(r,r, r, 0, Math.PI*2, false);
+ ctx.fill();
+ }
+
+});
+
Polygon = new Y.Class('Polygon', Shape, {
_cssClasses : 'portal layer shape polygon',
}
});
+// Er, this won't do. It's only a line-segment.
+Line = new Y.Class('Line', Polygon, {
+
+ init : function init(x,y){
+ Polygon.init.call(this, [x], [y]);
+ }
+
+});
+Line.fromPoints = function fromPoints(x1,y1, x2,y2){
+ return new Line(x2-x1, y2-y1).position(x1,y1);
+};
+
+
Triangle = new Y.Class('Triangle', Polygon, {
_cssClasses : 'portal layer shape polygon triangle',
Polygon.init.call(this, [x1,x2,x3], [y1,y2,y3]);
}
});
-
-Circle = new Y.Class('Circle', Shape, {
- _cssClasses : 'portal layer shape circle',
-
- init : function init(radius){
- Layer.init.call(this);
-
- var d = radius * 2;
- this.radius = radius;
- this.width(d)
- .height(d)
- .center(r,r);
- },
-
- drawShape : function drawShape(ctx){
- var r = this.radius
- // , cx = -this.originX
- // , cy = -this.originY ;
- // ctx.arc(cx,cy, r, 0, Math.PI*2, false);
- ctx.arc(r,r, r, 0, Math.PI*2, false);
- ctx.fill();
- }
-
-});
\ No newline at end of file
attr : Y.attr.methodize(),
- top : function top(x1,y1){
+ top : function top(x1,y1){
if ( x1 !== undefined && y1 !== undefined )
return new Loc(this.x1, this.y1);
else
return this.attr({ 'x1':x1, 'y1': y1 });
},
- bottom : function bottom(){ return new Loc(this.x2, this.y2); },
- left : function left(){ return new Loc(this.x1, this.y1); },
- right : function right(){ return new Loc(this.x2, this.y2); },
+ bottom : function bottom(x2,y2){
+ if ( x2 !== undefined && y2 !== undefined )
+ return new Loc(this.x2, this.y2);
+ else
+ return this.attr({ 'x2':x2, 'y2': y2 });
+ },
+ left : function left(x1,y1){
+ if ( x1 !== undefined && y1 !== undefined )
+ return new Loc(this.x1, this.y1);
+ else
+ return this.attr({ 'x1':x1, 'y1': y1 });
+ },
+ right : function right(x2,y2){
+ if ( x2 !== undefined && y2 !== undefined )
+ return new Loc(this.x2, this.y2);
+ else
+ return this.attr({ 'x2':x2, 'y2': y2 });
+ },
moveTo : function moveTo(x,y){
return new Loc.Rect(x,y, x+this.width,y+this.height);
// Tick once to draw grid, initial units
LBT.start();
LBT.stop();
+ LBT.loop.elapsedAtStop = 0;
setInterval(updateInfo, 1000);
updateInfo();
Grid = new Y.Class('Grid', Rect, {
_cssClasses : 'portal layer shape rect grid',
+ lineWidth : 0.5,
+ strokeStyle : '#6E6E6E',
+
init : function init(cols,rows, size){
this.cols = cols;
this.rows = rows;
, cols = this.cols
, w = this.canvasWidth
, h = this.canvasHeight
- // , cx = -this.originX
- // , cy = -this.originY
;
- ctx.lineWidth = 0.5;
- ctx.strokeStyle = '#6E6E6E';
+ ctx.lineWidth = this.lineWidth;
+ ctx.strokeStyle = this.strokeStyle;
for (var row=0, y=0; row<=rows; y = (++row) * size){
ctx.moveTo(0, y);
ctx.lineTo(w, y);
- // ctx.moveTo(cx, cy+y);
- // ctx.lineTo(cx+w, cy+y);
}
for (var col=0, x=0; col<=cols; x = (++col) * size){
ctx.moveTo(x, 0);
ctx.lineTo(x, h);
- // ctx.moveTo(cx+x, cy);
- // ctx.lineTo(cx+x, cy+h);
}
ctx.stroke();
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<title>math</title>
+<script type="text/javascript">document.write('<base href="http://'+window.location.host+'/">');</script>
+<link rel="stylesheet" href="css/reset.css" type="text/css" media="screen">
+<style type="text/css" media="screen">
+
+html, body { width:100%; height:100%;
+ font-family:Geogrotesque,Helvetica; color:#999; background-color:#D2E1A7; }
+body { font-family:Geogrotesque, Helvetica; font-size:12pt; }
+h1 { position:fixed; top:0; right:0; margin:0; padding:0; font-size:3em; color:#000; opacity:0.25; z-index:100; }
+ul, ol, li { list-style: none ! important; margin:0; padding:0; }
+
+.rounded { border-radius:1em; -moz-border-radius:1em; -webkit-border-radius:1em; }
+
+#plot { position:relative; top:1em; width:1000px; height:600px; margin:0 auto; background-color:#fff; }
+
+</style>
+</head>
+<body>
+
+<div id="plot"></div>
+
+<div id="scripts">
+<?php
+$scripts = array(
+ "lib/jquery-1.4.3.js",
+ "lib/jquery.sparkline.min.js",
+ "lib/jquery.hotkeys.js",
+
+ // "http://static.ukijs.org/pkg/0.3.8/uki.js",
+ // "http://static.ukijs.org/pkg/0.3.8/uki-more.js",
+
+ "src/lessly/future.js",
+
+ "src/Y/y.js.php",
+ "src/Y/modules/y.event.js",
+
+ "src/evt/evt.class.js",
+
+ "src/portal/util/loc.js",
+ "src/portal/layer.js",
+ "src/portal/shape.js",
+ "src/tanks/util/grid.js",
+
+ "src/portal/math/math.js",
+ "src/portal/math/vec.js",
+ "src/portal/math/line.js",
+
+ "test/math/math.test.js"
+);
+
+function js($src) {
+ echo " <script src=\"$src\" type=\"text/javascript\"></script>\n";
+}
+
+foreach ($scripts as $s) js($s);
+?>
+</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+PPU = 25;
+PX = 2.5/PPU;
+
+$(function(){
+
+plot = $('#plot');
+
+w = plot.width(); w2 = w/2;
+h = plot.height(); h2 = h/2;
+W = w/PPU; W2 = W/2;
+H = h/PPU; H2 = H/2;
+
+grid = new Grid( W, H, PPU ).appendTo(plot);
+grid.lineWidth = 1.0;
+grid.strokeStyle = '#E0E0E0'; //'#EEEEEE'; //
+grid.draw();
+
+P = new Layer()
+ .width(w).height(h)
+ .appendTo(grid);
+
+ctx = P.ctx;
+ctx.translate(w2, h2);
+ctx.scale(PPU, PPU);
+
+// Draw axes
+drawLine(-W2,0, W2,0, '#CCCCCC');
+drawLine(0,-H2, 0,H2, '#CCCCCC');
+
+testLine(1,2, 4,7, 'rgba(231,48,117, 0.5)', 'rgba(69,150,255, 1)');
+// testLine(-4,-2, 7,13, 'rgba(131,187,50, 0.75)', 'rgba(69,150,255, 1)');
+
+});
+
+function testLine(x1,y1, x2,y2, color, pcolor){
+ var t,p, line = new math.Line(x1,y1, x2,y2, 10);
+ drawLine(-W/2, line.calcY(-W2), line.calcX(H2), H2, color);
+ drawPoint(line.x1, line.y1);
+ drawPoint(line.x2, line.y2);
+
+ drawPoint(0, 0, pcolor);
+
+ t = 0;
+ p = line.pcalc(t);
+ drawPoint(p.x, p.y, pcolor);
+
+ t = 1;
+ p = line.pcalc(t);
+ drawPoint(p.x, p.y, pcolor);
+
+ t = -1;
+ p = line.pcalc(t);
+ drawPoint(p.x, p.y, pcolor);
+
+ return line;
+}
+
+
+function drawLine(x1,y1, x2,y2, color, width){
+ ctx.beginPath();
+ ctx.lineWidth = width || PX;
+ ctx.strokeStyle = color || '#000000';
+ ctx.moveTo(x1, -y1);
+ ctx.lineTo(x2, -y2);
+ ctx.stroke();
+ ctx.closePath();
+}
+
+function drawPoint(x,y, color, r){
+ r = r || 3.75;
+ var c = new Circle(r)
+ .position(w2-r + x*PPU, h2-r - y*PPU)
+ .attr({ 'fillStyle': color || 'rgba(0,0,0,0.5)' })
+ .appendTo(P)
+ .draw();
+ c.layer.attr('title', '('+x+','+y+')');
+ return c;
+}
+