From 1af8f41cc88e3c57bfabe6d4a5dcd83fc4a0e1bc Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Thu, 17 Apr 2014 02:32:53 -0400 Subject: further code bath, fix minimap orientation/translation --- assets/javascripts/rectangles/_env.js | 21 +-- assets/javascripts/rectangles/builder.js | 123 ---------------- assets/javascripts/rectangles/clipper.js | 182 ------------------------ assets/javascripts/rectangles/colors.js | 36 ----- assets/javascripts/rectangles/debug.js | 2 - assets/javascripts/rectangles/draw.js | 66 --------- assets/javascripts/rectangles/engine/builder.js | 123 ++++++++++++++++ assets/javascripts/rectangles/engine/clipper.js | 104 ++++++++++++++ assets/javascripts/rectangles/map/draw.js | 66 +++++++++ assets/javascripts/rectangles/map/ui.js | 103 ++++++++++++++ assets/javascripts/rectangles/models/rect.js | 131 +++++++++++++++++ assets/javascripts/rectangles/models/room.js | 39 +++++ assets/javascripts/rectangles/models/tree.js | 37 +++++ assets/javascripts/rectangles/models/vec2.js | 81 +++++++++++ assets/javascripts/rectangles/rect.js | 130 ----------------- assets/javascripts/rectangles/room.js | 39 ----- assets/javascripts/rectangles/sort.js | 37 ----- assets/javascripts/rectangles/tree.js | 37 ----- assets/javascripts/rectangles/util/colors.js | 36 +++++ assets/javascripts/rectangles/util/debug.js | 2 + assets/javascripts/rectangles/util/mouse.js | 114 +++++++++++++++ assets/javascripts/rectangles/util/sort.js | 37 +++++ assets/javascripts/rectangles/util/wheel.js | 62 ++++++++ assets/javascripts/rectangles/vec2.js | 81 ----------- assets/javascripts/rectangles/wheel.js | 64 --------- rectangles-canvas-only.html | 25 ++-- rectangles.html | 24 ++-- 27 files changed, 975 insertions(+), 827 deletions(-) delete mode 100644 assets/javascripts/rectangles/builder.js delete mode 100644 assets/javascripts/rectangles/clipper.js delete mode 100644 assets/javascripts/rectangles/colors.js delete mode 100644 assets/javascripts/rectangles/debug.js delete mode 100644 assets/javascripts/rectangles/draw.js create mode 100644 assets/javascripts/rectangles/engine/builder.js create mode 100644 assets/javascripts/rectangles/engine/clipper.js create mode 100644 assets/javascripts/rectangles/map/draw.js create mode 100644 assets/javascripts/rectangles/map/ui.js create mode 100644 assets/javascripts/rectangles/models/rect.js create mode 100644 assets/javascripts/rectangles/models/room.js create mode 100644 assets/javascripts/rectangles/models/tree.js create mode 100644 assets/javascripts/rectangles/models/vec2.js delete mode 100644 assets/javascripts/rectangles/rect.js delete mode 100644 assets/javascripts/rectangles/room.js delete mode 100644 assets/javascripts/rectangles/sort.js delete mode 100644 assets/javascripts/rectangles/tree.js create mode 100644 assets/javascripts/rectangles/util/colors.js create mode 100644 assets/javascripts/rectangles/util/debug.js create mode 100644 assets/javascripts/rectangles/util/mouse.js create mode 100644 assets/javascripts/rectangles/util/sort.js create mode 100644 assets/javascripts/rectangles/util/wheel.js delete mode 100644 assets/javascripts/rectangles/vec2.js delete mode 100644 assets/javascripts/rectangles/wheel.js diff --git a/assets/javascripts/rectangles/_env.js b/assets/javascripts/rectangles/_env.js index 11e01ba..afbf161 100644 --- a/assets/javascripts/rectangles/_env.js +++ b/assets/javascripts/rectangles/_env.js @@ -2,20 +2,24 @@ var environment = new function(){} environment.init = function(){ window.scene && scene.camera.move({ - "x": 240, - "y": -1000, - "z": 240, - "rotationX": -PI/2, - "rotationY": 0 // PI + "x": 0, + "y": 1000, + "z": 0, + "rotationX": PI/2, + "rotationY": PI }) + clipper.rooms.push( new room ({ + rect: new rect(-100,-100, 100,100), + height: 400, + })) clipper.rooms.push( new room ({ rect: new rect(100,100, 200,300), height: 400, })) clipper.rooms.push( new room ({ rect: new rect(200,300, 300,500), - height: 300, + height: 400, })) clipper.rooms.push( new room ({ rect: new rect(300,100, 600,300), @@ -23,7 +27,7 @@ environment.init = function(){ })) clipper.rooms.push( new room ({ rect: new rect(400,200, 700,400), - height: 500, + height: 400, })) builder.init() @@ -31,5 +35,6 @@ environment.init = function(){ window.scene && scene.update() } environment.update = function(t){ - clipper.animate() + map.animate() + z = false } diff --git a/assets/javascripts/rectangles/builder.js b/assets/javascripts/rectangles/builder.js deleted file mode 100644 index edca2ed..0000000 --- a/assets/javascripts/rectangles/builder.js +++ /dev/null @@ -1,123 +0,0 @@ -var builder = new function(){ - var base = this - base.tube = new Tube () - - var els = [] - - base.init = function(){ - base.bind() - } - - base.bind = function(){ - base.tube.on("clipper:update", rebuild) - } - - base.wheel = new wheel({ - el: document.querySelector("#map"), - update: function(e, val, delta){ - console.log(e.clientX, e.clientY, delta) - } - }) - - function rebuild(){ - if (window.scene) { - clear() - build() - } - } - function build (){ - clipper.regions.forEach(function(r){ - walls(r).forEach(function(el){ - els.push(el) - scene.add(el) - }) - }) - } - function clear (){ - els.forEach(function(el){ - scene.remove(el) - }) - els = [] - } - - function walls (r){ - var list = [], el = null - - var width = r.x.length() - var depth = r.y.length() - var height = clipper.rooms[r.id].height - - if (r.sides & FRONT) { - el = wall('.front') - el.width = width - el.height = height - el.rotationY = PI - el.x = r.x.a + width/2 - el.z = r.y.a - list.push(el) - } - if (r.sides & BACK) { - var el = wall('.back') - el.width = width - el.height = height - el.rotationY = 0 - el.x = r.x.b - width/2 - el.z = r.y.b - list.push(el) - } - if (r.sides & LEFT) { - el = wall('.left') - el.rotationY = HALF_PI - el.height = height - el.width = depth - el.x = r.x.a - el.z = r.y.a + depth/2 - list.push(el) - } - if (r.sides & RIGHT) { - el = wall('.right') - el.rotationY = -HALF_PI - el.height = height - el.width = depth - el.x = r.x.b - el.z = r.y.b - depth/2 - list.push(el) - } - - el = wall('.bottom') - el.height = depth - el.width = width - el.x = r.x.a + width/2 - el.y = 0 - el.z = r.y.a + depth/2 - el.rotationX = PI/2 - el.el.style.backgroundColor = "#f00" - list.push(el) - - if (r.sides != 0) { - el = wall('.top') - el.height = depth - el.width = width - el.x = r.x.a + width/2 - el.y = height - el.z = r.y.a + depth/2 - el.rotationX = -PI/2 - el.el.style.backgroundColor = "#00f" - list.push(el) - } - - function wall(klass){ - var el = new MX.Object3D(".face" + (klass || "")) - el.width = el.height = el.scaleX = el.scaleY = el.scaleZ = 1 - el.z = el.y = el.x = 0 - el.y = height/2 - el.type = "Face" - el.el.style.opacity = 1.0 - return el - } - - return list - } - -} - diff --git a/assets/javascripts/rectangles/clipper.js b/assets/javascripts/rectangles/clipper.js deleted file mode 100644 index e712b71..0000000 --- a/assets/javascripts/rectangles/clipper.js +++ /dev/null @@ -1,182 +0,0 @@ -window.ctx = window.w = window.h = null; - -var clipper = new function(){ - var base = this - var canvas = document.createElement("canvas") - var ctx = window.ctx = canvas.getContext("2d") - var w = window.w = canvas.width = 500 - var h = window.h = canvas.height = 500 - var regions = [] - document.querySelector("#map").appendChild(canvas) - - var rooms = base.rooms = [] - - base.creating = false - base.dragging = false - - var modified = true - base.mouse = new rect(0,0,0,0) - - base.init = function (){ - base.bind() - } - base.animate = function(){ - clear_canvas() - - if (modified) { - solve_rects() - builder.tube("clipper:update") - } - draw_ruler() - draw_regions(base.regions) - draw_mouse(base.mouse) - modified = z = false - } - - base.add_room = function(r){ - rooms.push( new room({ - id: base.rooms.length, - rect: r, - }) ) - } - - base.bind = function(){ - canvas.addEventListener("mousedown", function(e){ - e.stopPropagation() - var x = e.pageX, y = e.pageY - base.mouse = new rect (x,y) - if (e.shiftKey) { - base.mouse.quantize(10) - } - - var intersects = rooms.filter(function(r){ - return r.focused = r.rect.contains(x,y) - }) - - if (intersects.length){ - clipper.dragging = intersects[0] - } - else { - clipper.creating = true - } - if (e.shiftKey && clipper.dragging) { - clipper.dragging.rect.quantize(10) - } - }) - canvas.addEventListener("mousemove", function(e){ - e.stopPropagation() - var x, y - if (e.shiftKey) { - x = quantize( e.pageX, 10 ) - y = quantize( e.pageY, 10 ) - } - else { - x = e.pageX - y = e.pageY - } - - base.mouse.x.b = x - base.mouse.y.b = y - - if (clipper.dragging) { - clipper.dragging.rect.translation.a = base.mouse.x.magnitude() - clipper.dragging.rect.translation.b = base.mouse.y.magnitude() - } - else if (clipper.creating) { - base.mouse.x.b = x - base.mouse.y.b = y - } - else { - base.mouse.x.a = base.mouse.x.b - base.mouse.y.a = base.mouse.y.b - } - }) - document.addEventListener("mouseup", function(e){ - e.stopPropagation() - if (clipper.creating) { - if (base.mouse.height() != 0 && base.mouse.width() != 0) { - base.add_room( base.mouse.translate() ) - } - } - if (clipper.dragging) { - clipper.dragging.rect.translate() - } - base.mouse = new rect(e.pageX, e.pageY) - clipper.creating = clipper.dragging = false - modified = true - }) - } - - function solve_rects(){ - - for (var i = 0; i < base.rooms.length; i++) { - base.rooms[i].id = i - base.rooms[i].reset() - } - - var rooms = sort_rooms_by_position( base.rooms ) - - var regions = [] - - var left, right - for (var i = 0; i < rooms.length; i++) { - left = rooms[i] - for (var j = i+1; j < rooms.length; j++) { - right = rooms[j] - if (left.rect.intersects(right.rect)) { - left.clipTo(right.rect) - right.clipTo(left.rect) - } - if (left.rect.x.b < right.rect.x.a) { - break - } - } - } - for (var i = 0; i < rooms.length; i++) { - rooms[i].regions = rooms[i].regions.filter(function(r){ return !!r }) - regions = regions.concat(rooms[i].regions) - } - - regions = sort_rects_by_area( regions ) - - var ty = new tree (regions[0].y.a, [regions[0]]) - var tx = new tree (regions[0].x.a, ty) - var ttx, tty - - for (var i = 1; i < regions.length; i++) { - ttx = tx.add (regions[i].x.a, null) - if (ttx.data) { - tty = ttx.data.add (regions[i].y.a, null) - // duplicate polygon? - if (tty.data) { - tty.data.forEach(function(yy, ii){ - if (yy.intersects(regions[i])) { - if (yy.area() > regions[i].area()) { - regions[i].dupe = true - } - else { - yy.dupe = true - tty.data[ii] = regions[i] - } - } - }) - } - else { - tty.data = [regions[i]] - } - } - else { - ttx.data = new tree (regions[i].y.a, [regions[i]]) - } - } - - base.regions = sort_rects_by_position(regions) - } - - // generate floor and ceiling for some regions - // generate walls from surviving regions - // generate ceiling-walls where ceiling has discontinuity - - return base -} - diff --git a/assets/javascripts/rectangles/colors.js b/assets/javascripts/rectangles/colors.js deleted file mode 100644 index 3bdebbc..0000000 --- a/assets/javascripts/rectangles/colors.js +++ /dev/null @@ -1,36 +0,0 @@ -(function(){ - var color_palettes = { - alpha: [ - "rgba(0,0,0,0.1)", - ], - redblue: [ - "rgba(0,0,0,0.2)", - "rgba(255,0,0,0.2)", - "rgba(0,0,255,0.2)", - "rgba(0,255,0,0.2)", - ], - gray: [ - "rgba(0,0,0,0.1)", - "rgba(0,0,0,0.2)", - "rgba(0,0,0,0.3)", - "rgba(0,0,0,0.4)", - ], - colors: [ - "rgba(255,0,0,0.5)", - "rgba(255,128,0,0.5)", - "rgba(128,255,0,0.5)", - "rgba(0,255,0,0.5)", - "rgba(0,255,128,0.5)", - "rgba(0,128,255,0.5)", - "rgba(0,0,255,0.5)", - "rgba(128,0,255,0.5)", - "rgba(255,0,255,0.5)", - "rgba(255,0,128,0.5)", - ] - } - - var select = document.querySelector("#palette") - select.addEventListener("change", function(){ colors = color_palettes[select.value] }) - - window.colors = color_palettes[select.value] -})() diff --git a/assets/javascripts/rectangles/debug.js b/assets/javascripts/rectangles/debug.js deleted file mode 100644 index 437abb8..0000000 --- a/assets/javascripts/rectangles/debug.js +++ /dev/null @@ -1,2 +0,0 @@ -window.z = true; -document.body.addEventListener("mousedown", function(){ z = true }) diff --git a/assets/javascripts/rectangles/draw.js b/assets/javascripts/rectangles/draw.js deleted file mode 100644 index eb3dece..0000000 --- a/assets/javascripts/rectangles/draw.js +++ /dev/null @@ -1,66 +0,0 @@ -function clear_canvas(){ - ctx.fillStyle = "rgba(255,255,255,0.7)" - ctx.clearRect(0,0,w,h) - ctx.fillRect(0,0,w,h) -} -function draw_ruler(){ - ctx.strokeStyle = "rgba(80,80,80,0.5)" - ctx.lineWidth = 1 - var len = 5 - for (var i = 0.5; i < w; i += 10) { - line(i, 0, i, len) - line(0, i, len, i) - } -} -function line (x,y,a,b,translation){ - if (translation) { - x += translation.a - a += translation.a - y += translation.b - b += translation.b - } - ctx.beginPath() - ctx.moveTo(x,y) - ctx.lineTo(a,b) - ctx.stroke() -} -function draw_regions(regions){ - for (var i = 0; i < regions.length; i++) { - if (regions[i].dupe) continue - ctx.fillStyle = colors[i % colors.length] - fill_region(regions[i]) - stroke_sides(regions[i]) - } -} -function draw_mouse(mouse){ - ctx.fillStyle = "rgba(255,0,0,0.4)"; - ctx.beginPath(); - ctx.arc(mouse.x.b, mouse.y.b, 5, 0, 2*Math.PI, false); - ctx.fill(); - - if (mouse.width() != 0 && mouse.height() != 0) { - if (clipper.dragging) { - stroke_rect(mouse) - } - else { - ctx.fillStyle = "rgba(255,255,0,0.5)" - fill_region( mouse.clone().translate() ) - } - } -} - -function fill_region(r){ - ctx.fillRect(r.x.a + r.translation.a, - r.y.a + r.translation.b, - r.x.length(), - r.y.length()) -} -function stroke_sides (r){ - if (r.sides & FRONT) line(r.x.a, r.y.a, r.x.b, r.y.a) - if (r.sides & BACK) line(r.x.a, r.y.b, r.x.b, r.y.b) - if (r.sides & LEFT) line(r.x.a, r.y.a, r.x.a, r.y.b) - if (r.sides & RIGHT) line(r.x.b, r.y.a, r.x.b, r.y.b) -} -function stroke_rect (r){ - line(r.x.a, r.y.a, r.x.b, r.y.b, r.translation) -} diff --git a/assets/javascripts/rectangles/engine/builder.js b/assets/javascripts/rectangles/engine/builder.js new file mode 100644 index 0000000..edca2ed --- /dev/null +++ b/assets/javascripts/rectangles/engine/builder.js @@ -0,0 +1,123 @@ +var builder = new function(){ + var base = this + base.tube = new Tube () + + var els = [] + + base.init = function(){ + base.bind() + } + + base.bind = function(){ + base.tube.on("clipper:update", rebuild) + } + + base.wheel = new wheel({ + el: document.querySelector("#map"), + update: function(e, val, delta){ + console.log(e.clientX, e.clientY, delta) + } + }) + + function rebuild(){ + if (window.scene) { + clear() + build() + } + } + function build (){ + clipper.regions.forEach(function(r){ + walls(r).forEach(function(el){ + els.push(el) + scene.add(el) + }) + }) + } + function clear (){ + els.forEach(function(el){ + scene.remove(el) + }) + els = [] + } + + function walls (r){ + var list = [], el = null + + var width = r.x.length() + var depth = r.y.length() + var height = clipper.rooms[r.id].height + + if (r.sides & FRONT) { + el = wall('.front') + el.width = width + el.height = height + el.rotationY = PI + el.x = r.x.a + width/2 + el.z = r.y.a + list.push(el) + } + if (r.sides & BACK) { + var el = wall('.back') + el.width = width + el.height = height + el.rotationY = 0 + el.x = r.x.b - width/2 + el.z = r.y.b + list.push(el) + } + if (r.sides & LEFT) { + el = wall('.left') + el.rotationY = HALF_PI + el.height = height + el.width = depth + el.x = r.x.a + el.z = r.y.a + depth/2 + list.push(el) + } + if (r.sides & RIGHT) { + el = wall('.right') + el.rotationY = -HALF_PI + el.height = height + el.width = depth + el.x = r.x.b + el.z = r.y.b - depth/2 + list.push(el) + } + + el = wall('.bottom') + el.height = depth + el.width = width + el.x = r.x.a + width/2 + el.y = 0 + el.z = r.y.a + depth/2 + el.rotationX = PI/2 + el.el.style.backgroundColor = "#f00" + list.push(el) + + if (r.sides != 0) { + el = wall('.top') + el.height = depth + el.width = width + el.x = r.x.a + width/2 + el.y = height + el.z = r.y.a + depth/2 + el.rotationX = -PI/2 + el.el.style.backgroundColor = "#00f" + list.push(el) + } + + function wall(klass){ + var el = new MX.Object3D(".face" + (klass || "")) + el.width = el.height = el.scaleX = el.scaleY = el.scaleZ = 1 + el.z = el.y = el.x = 0 + el.y = height/2 + el.type = "Face" + el.el.style.opacity = 1.0 + return el + } + + return list + } + +} + diff --git a/assets/javascripts/rectangles/engine/clipper.js b/assets/javascripts/rectangles/engine/clipper.js new file mode 100644 index 0000000..13fc378 --- /dev/null +++ b/assets/javascripts/rectangles/engine/clipper.js @@ -0,0 +1,104 @@ + +var clipper = new function(){ + var base = this + + var rooms = base.rooms = [] + var regions = base.regions = [] + + var modified = true + + base.init = function(){ + base.bind() + base.update() + } + + base.bind = function(){ + map.ui.mouse.tube.on("up", function(){ base.update() }) + } + + base.update = function(){ + clipper.solve_rects() + builder.tube("clipper:update") + } + + base.add_room = function(r){ + rooms.push( new room({ + id: base.rooms.length, + rect: r, + }) ) + } + + base.solve_rects = function(){ + if (base.rooms.length == 0) return; + + for (var i = 0; i < base.rooms.length; i++) { + base.rooms[i].id = i + base.rooms[i].reset() + } + + var rooms = sort_rooms_by_position( base.rooms ) + + var regions = [] + + var left, right + for (var i = 0; i < rooms.length; i++) { + left = rooms[i] + for (var j = i+1; j < rooms.length; j++) { + right = rooms[j] + if (left.rect.intersects(right.rect)) { + left.clipTo(right.rect) + right.clipTo(left.rect) + } + if (left.rect.x.b < right.rect.x.a) { + break + } + } + } + for (var i = 0; i < rooms.length; i++) { + rooms[i].regions = rooms[i].regions.filter(function(r){ return !!r }) + regions = regions.concat(rooms[i].regions) + } + + regions = sort_rects_by_area( regions ) + + var ty = new tree (regions[0].y.a, [regions[0]]) + var tx = new tree (regions[0].x.a, ty) + var ttx, tty + + for (var i = 1; i < regions.length; i++) { + ttx = tx.add (regions[i].x.a, null) + if (ttx.data) { + tty = ttx.data.add (regions[i].y.a, null) + // duplicate polygon? + if (tty.data) { + tty.data.forEach(function(yy, ii){ + if (yy.intersects(regions[i])) { + if (yy.area() > regions[i].area()) { + regions[i].dupe = true + } + else { + yy.dupe = true + tty.data[ii] = regions[i] + } + } + }) + } + else { + tty.data = [regions[i]] + } + } + else { + ttx.data = new tree (regions[i].y.a, [regions[i]]) + } + } + + base.regions = sort_rects_by_position(regions) + } + + // generate floor and ceiling for some regions + // generate walls from surviving regions + // generate ceiling-walls where ceiling has discontinuity + + return base +} + diff --git a/assets/javascripts/rectangles/map/draw.js b/assets/javascripts/rectangles/map/draw.js new file mode 100644 index 0000000..eb3dece --- /dev/null +++ b/assets/javascripts/rectangles/map/draw.js @@ -0,0 +1,66 @@ +function clear_canvas(){ + ctx.fillStyle = "rgba(255,255,255,0.7)" + ctx.clearRect(0,0,w,h) + ctx.fillRect(0,0,w,h) +} +function draw_ruler(){ + ctx.strokeStyle = "rgba(80,80,80,0.5)" + ctx.lineWidth = 1 + var len = 5 + for (var i = 0.5; i < w; i += 10) { + line(i, 0, i, len) + line(0, i, len, i) + } +} +function line (x,y,a,b,translation){ + if (translation) { + x += translation.a + a += translation.a + y += translation.b + b += translation.b + } + ctx.beginPath() + ctx.moveTo(x,y) + ctx.lineTo(a,b) + ctx.stroke() +} +function draw_regions(regions){ + for (var i = 0; i < regions.length; i++) { + if (regions[i].dupe) continue + ctx.fillStyle = colors[i % colors.length] + fill_region(regions[i]) + stroke_sides(regions[i]) + } +} +function draw_mouse(mouse){ + ctx.fillStyle = "rgba(255,0,0,0.4)"; + ctx.beginPath(); + ctx.arc(mouse.x.b, mouse.y.b, 5, 0, 2*Math.PI, false); + ctx.fill(); + + if (mouse.width() != 0 && mouse.height() != 0) { + if (clipper.dragging) { + stroke_rect(mouse) + } + else { + ctx.fillStyle = "rgba(255,255,0,0.5)" + fill_region( mouse.clone().translate() ) + } + } +} + +function fill_region(r){ + ctx.fillRect(r.x.a + r.translation.a, + r.y.a + r.translation.b, + r.x.length(), + r.y.length()) +} +function stroke_sides (r){ + if (r.sides & FRONT) line(r.x.a, r.y.a, r.x.b, r.y.a) + if (r.sides & BACK) line(r.x.a, r.y.b, r.x.b, r.y.b) + if (r.sides & LEFT) line(r.x.a, r.y.a, r.x.a, r.y.b) + if (r.sides & RIGHT) line(r.x.b, r.y.a, r.x.b, r.y.b) +} +function stroke_rect (r){ + line(r.x.a, r.y.a, r.x.b, r.y.b, r.translation) +} diff --git a/assets/javascripts/rectangles/map/ui.js b/assets/javascripts/rectangles/map/ui.js new file mode 100644 index 0000000..05fad90 --- /dev/null +++ b/assets/javascripts/rectangles/map/ui.js @@ -0,0 +1,103 @@ +/* +*/ + +window.ctx = window.w = window.h = null; + +var map = new function(){ + var base = this + base.bounds = new vec2(500,500) + base.center = new vec2(0,0) + + var canvas = document.createElement("canvas") + var ctx = window.ctx = canvas.getContext("2d") + var w = window.w = canvas.width = 500 + var h = window.h = canvas.height = 500 + document.querySelector("#map").appendChild(canvas) + + base.animate = function(){ + ctx.save() + clear_canvas() + draw_ruler() + + ctx.translate( map.center.a + map.bounds.a/2, map.center.b + map.bounds.b/2 ) + ctx.scale( -1, 1 ) + + draw_regions(clipper.regions) + draw_mouse(map.ui.mouse.cursor) + + ctx.restore() + } +} + +map.ui = new function(){ + var base = this + base.el = document.querySelector("#map") + + base.mouse = new mouse({ + el: base.el, + down: down, + move: move, + drag: drag, + up: up, + }) + + base.wheel = new wheel({ + el: base.el, + update: function(e, val, delta){ + // do something with val + }, + }) + + function down (e, cursor){ + cursor.x.add( map.center.a + map.bounds.a/2 ) + cursor.y.add( map.center.b - map.bounds.b/2 ) + + var intersects = clipper.rooms.filter(function(r){ + return r.focused = r.rect.contains(cursor) + }) + + if (intersects.length){ + base.dragging = intersects[0] + } + else { + base.creating = true + } + + if (e.shiftKey && base.dragging) { + base.dragging.rect.quantize(10) + } + } + + function move (e, cursor) { + cursor.x.add( map.center.a + map.bounds.a/2 ) + cursor.y.add( map.center.b - map.bounds.b/2 ) + z=true + } + + function drag (e, cursor) { + cursor.x.b += map.center.a + map.bounds.a/2 + cursor.y.b += map.center.b - map.bounds.b/2 + + if (base.dragging) { + base.dragging.rect.translation.a = cursor.x.magnitude() + base.dragging.rect.translation.b = cursor.y.magnitude() + } + } + + function up (e, cursor) { + + if (base.creating) { + if (cursor.height() != 0 && cursor.width() != 0) { + cursor.x.abs() + cursor.y.abs() + clipper.add_room( cursor ) + } + } + + if (base.dragging) { + base.dragging.rect.translate() + } + + base.creating = base.dragging = false + } +} \ No newline at end of file diff --git a/assets/javascripts/rectangles/models/rect.js b/assets/javascripts/rectangles/models/rect.js new file mode 100644 index 0000000..548e16a --- /dev/null +++ b/assets/javascripts/rectangles/models/rect.js @@ -0,0 +1,131 @@ +var FRONT = 0x1, BACK = 0x2, LEFT = 0x4, RIGHT = 0x8 + +window.rect = (function(){ + var rect = function (x0,y0,x1,y1){ + if (x0 instanceof vec2) { + this.x = x0 + this.y = y0 + } + else if (x1 === undefined) { + this.x = new vec2(x0,x0) + this.y = new vec2(y0,y0) + } + else { + this.x = new vec2(x0,x1) + this.y = new vec2(y0,y1) + } + this.translation = new vec2(0,0) + this.sides = FRONT | BACK | LEFT | RIGHT + } + rect.prototype.clone = function(){ + return new rect( this.x.clone(), this.y.clone() ) + } + rect.prototype.center = function(){ + return new vec2(this.x.midpoint(), this.y.midpoint()) + } + rect.prototype.area = function(){ + return this.x.length() * this.y.length() + } + rect.prototype.translate = function(translation){ + var translation = translation || this.translation + this.x.abs().add(translation.a) + this.y.abs().add(translation.b) + this.translation.a = this.translation.b = 0 + return this + } + rect.prototype.contains = function(x,y){ + return this.x.contains(x) && this.y.contains(y) + } + rect.prototype.intersects = function(r){ + return this.x.intersects(r.x) && this.y.intersects(r.y) + } + rect.prototype.width = function(){ return this.x.length() } + rect.prototype.height = function(){ return this.y.length() } + rect.prototype.toString = function(){ + var sides = "" + if (this.sides & FRONT) sides += "front " + if (this.sides & BACK) sides += "back " + if (this.sides & LEFT) sides += "left " + if (this.sides & RIGHT) sides += "right " + var s = "[" + this.x.toString() + " " + this.y.toString() + "] " + sides + return s + } + rect.prototype.quantize = function(n){ + this.x.quantize(n) + this.y.quantize(n) + } + rect.prototype.split = function(r){ + var rz = this + var splits = [] + var split_contains = 0 + var x_intervals = [], y_intervals = [] + var sides = this.sides + + // Split vertically + if (this.x.contains(r.x.a) && r.x.contains(this.x.b)) { + x_intervals.push([ new vec2( this.x.a, r.x.a ), LEFT ]) + x_intervals.push([ new vec2( r.x.a, this.x.b ), RIGHT ]) + split_contains |= RIGHT + } + + else if (r.x.contains(this.x.a) && this.x.contains(r.x.b)) { + x_intervals.push([ new vec2( this.x.a, r.x.b ), LEFT ]) + x_intervals.push([ new vec2( r.x.b, this.x.b ), RIGHT ]) + split_contains |= LEFT + } + + else if (this.x.contains(r.x.a) && this.x.contains(r.x.b)) { + x_intervals.push([ new vec2( this.x.a, r.x.a ), LEFT ]) + x_intervals.push([ new vec2( r.x.a, r.x.b ), 0 ]) + x_intervals.push([ new vec2( r.x.b, this.x.b ), RIGHT ]) + split_contains |= LEFT | RIGHT + } + + else { // if (r.x.contains(this.x.a) && r.x.contains(r.x.b)) { + x_intervals.push([ new vec2( this.x.a, this.x.b ), LEFT | RIGHT ]) + split_contains |= LEFT | RIGHT + } + + // Split horizontally + if (this.y.contains(r.y.a) && r.y.contains(this.y.b)) { + y_intervals.push([ new vec2( this.y.a, r.y.a ), FRONT ]) + y_intervals.push([ new vec2( r.y.a, this.y.b ), BACK ]) + split_contains |= BACK + } + + else if (r.y.contains(this.y.a) && this.y.contains(r.y.b)) { + y_intervals.push([ new vec2( this.y.a, r.y.b ), FRONT ]) + y_intervals.push([ new vec2( r.y.b, this.y.b ), BACK ]) + split_contains |= FRONT + } + + else if (this.y.contains(r.y.a) && this.y.contains(r.y.b)) { + y_intervals.push([ new vec2( this.y.a, r.y.a ), FRONT ]) + y_intervals.push([ new vec2( r.y.a, r.y.b ), 0 ]) + y_intervals.push([ new vec2( r.y.b, this.y.b ), BACK ]) + split_contains |= FRONT | BACK + } + + else { // if (r.y.contains(this.y.a) && this.y.contains(r.y.b)) { + y_intervals.push([ new vec2( this.y.a, this.y.b ), FRONT | BACK ]) + split_contains |= FRONT | BACK + } + + x_intervals.forEach(function(x){ + y_intervals.forEach(function(y){ + var rn = new rect(x[0], y[0]) + rn.id = rz.id + rn.sides = ((x[1] | y[1]) & sides) + if (r.intersects(rn)) { + rn.sides = 0 + } + rn.focused = rz.focused + splits.push(rn) + }) + }) + return splits + } + + return rect + +})() diff --git a/assets/javascripts/rectangles/models/room.js b/assets/javascripts/rectangles/models/room.js new file mode 100644 index 0000000..8c9d67d --- /dev/null +++ b/assets/javascripts/rectangles/models/room.js @@ -0,0 +1,39 @@ +window.room = (function(){ + + var room = function(opt){ + this.id = opt.id || clipper.rooms.length + this.rect = opt.rect + this.regions = [] + this.height = opt.height || 200 + this.focused = false + } + + room.prototype.toString = function(){ + return this.rect.toString() + } + + room.prototype.reset = function(){ + var copy = this.rect.clone() + copy.id = this.id + copy.sides = FRONT | BACK | LEFT | RIGHT + this.regions = [ copy ] + } + + room.prototype.clipTo = function(r){ + // for each of this rect's regions split the region if necessary + var regions = this.regions + var splits + + for (var i = 0, len = regions.length; i < len; i++) { + if (regions[i] && regions[i].intersects(r)) { + splits = regions[i].split(r) + regions = regions.concat(splits) + regions[i] = null + } + } + this.regions = regions + } + + return room + +})() diff --git a/assets/javascripts/rectangles/models/tree.js b/assets/javascripts/rectangles/models/tree.js new file mode 100644 index 0000000..577c41a --- /dev/null +++ b/assets/javascripts/rectangles/models/tree.js @@ -0,0 +1,37 @@ +var tree = function(n, data){ + this.lo = null + this.hi = null + this.value = n + this.data = data +} +tree.prototype.find = function(n){ + if (n == this.value) return this + if (n < this.value) return this.lo ? this.lo.find(n) : this + if (n > this.value) return this.hi ? this.hi.find(n) : this +} +tree.prototype.add = function(n, data){ + var closest = this.find(n) + if (n == closest.value) return closest + if (n < closest.value) return closest.lo = new tree(n, data) + if (n > closest.value) return closest.hi = new tree(n, data) +} +tree.prototype.toArray = function(){ + var a = [] + if (this.lo) a = a.concat(this.lo.toArray()) + a.push(this.data) + if (this.hi) a = a.concat(this.hi.toArray()) + return a +} +tree.prototype.toString = function(){ + var s = ""; + if (this.lo) s += this.lo.toString() + s += this.value + "," + if (this.hi) s += this.hi.toString() + return s +} +tree.prototype.depth = function(){ + if (this.lo && this.hi) return 1 + max(this.lo.depth(), this.hi.depth()) + else if (this.lo) return 1 + this.lo.depth() + else if (this.hi) return 1 + this.hi.depth() + else return 0 +} diff --git a/assets/javascripts/rectangles/models/vec2.js b/assets/javascripts/rectangles/models/vec2.js new file mode 100644 index 0000000..4e2ad36 --- /dev/null +++ b/assets/javascripts/rectangles/models/vec2.js @@ -0,0 +1,81 @@ +function vec2(a,b){ + this.a = a + this.b = b +} +vec2.prototype.magnitude = function(){ + return this.b-this.a +} +vec2.prototype.length = function(){ + return abs(this.b-this.a) +} +vec2.prototype.clone = function(){ + return new vec2(this.a, this.b) +} +vec2.prototype.abs = function(){ + if (this.b < this.a) { + this.a = this.a ^ this.b + this.b = this.a ^ this.b + this.a = this.a ^ this.b + } + return this +} +vec2.prototype.midpoint = function(){ + return lerp(0.5, this.a, this.b) +} +vec2.prototype.eq = function(v){ + return this.a == v.a && this.b == v.b +} +vec2.prototype.add = function(n){ + this.a += n + this.b += n +} +vec2.prototype.sub = function(n){ + this.a -= n + this.b -= n +} +vec2.prototype.mul = function(n){ + this.a *= n + this.b *= n +} +vec2.prototype.div = function(n){ + this.a /= n + this.b /= n +} +vec2.normalize = function(){ + var dim = max(this.a, this.b) + this.a = this.a/dim + this.b = this.b/dim +} +vec2.prototype.contains = function(n){ + return this.a <= n && n <= this.b +} +vec2.prototype.intersects = function(v){ + if (this.a < v.a) { + return (v.a < this.b && this.b <= v.b) || (this.a < v.b && v.b <= this.b) + } + else if (this.a == v.a) { + return true + } + else if (this.a > v.a) { + return (this.a < v.b && v.b <= this.b) || (v.a < this.b && this.b <= v.b) + } +} +vec2.prototype.union = function(v){ + if (this.intersects(v)) { + return new vec2( min(this.a,v.a), max(this.b, v.b) ) + } +} +vec2.prototype.intersection = function(v){ + if (this.intersects(v)) { + return new vec2( max(this.a,v.a), min(this.b, v.b) ) + } +} +vec2.prototype.toString = function(){ + return "[" + this.a + " " + this.b + "]" +} +vec2.prototype.quantize = function(n){ + n = n || 10 + this.a = quantize(this.a, n) + this.b = quantize(this.b, n) +} + diff --git a/assets/javascripts/rectangles/rect.js b/assets/javascripts/rectangles/rect.js deleted file mode 100644 index 50debbc..0000000 --- a/assets/javascripts/rectangles/rect.js +++ /dev/null @@ -1,130 +0,0 @@ -var FRONT = 0x1, BACK = 0x2, LEFT = 0x4, RIGHT = 0x8 - -window.rect = (function(){ - var rect = function (x0,y0,x1,y1){ - if (x0 instanceof vec2) { - this.x = x0 - this.y = y0 - } - else if (x1 === undefined) { - this.x = new vec2(x0,x0) - this.y = new vec2(y0,y0) - } - else { - this.x = new vec2(x0,x1) - this.y = new vec2(y0,y1) - } - this.translation = new vec2(0,0) - this.sides = FRONT | BACK | LEFT | RIGHT - } - rect.prototype.clone = function(){ - return new rect( this.x.clone(), this.y.clone() ) - } - rect.prototype.center = function(){ - return new vec2(this.x.midpoint(), this.y.midpoint()) - } - rect.prototype.area = function(){ - return this.x.length() * this.y.length() - } - rect.prototype.translate = function(){ - this.x.abs().add(this.translation.a) - this.y.abs().add(this.translation.b) - this.translation.a = this.translation.b = 0 - return this - } - rect.prototype.contains = function(x,y){ - return this.x.contains(x) && this.y.contains(y) - } - rect.prototype.intersects = function(r){ - return this.x.intersects(r.x) && this.y.intersects(r.y) - } - rect.prototype.width = function(){ return this.x.length() } - rect.prototype.height = function(){ return this.y.length() } - rect.prototype.toString = function(){ - var sides = "" - if (this.sides & FRONT) sides += "front " - if (this.sides & BACK) sides += "back " - if (this.sides & LEFT) sides += "left " - if (this.sides & RIGHT) sides += "right " - var s = "[" + this.x.toString() + " " + this.y.toString() + "] " + sides - return s - } - rect.prototype.quantize = function(n){ - this.x.quantize(n) - this.y.quantize(n) - } - rect.prototype.split = function(r){ - var rz = this - var splits = [] - var split_contains = 0 - var x_intervals = [], y_intervals = [] - var sides = this.sides - - // Split vertically - if (this.x.contains(r.x.a) && r.x.contains(this.x.b)) { - x_intervals.push([ new vec2( this.x.a, r.x.a ), LEFT ]) - x_intervals.push([ new vec2( r.x.a, this.x.b ), RIGHT ]) - split_contains |= RIGHT - } - - else if (r.x.contains(this.x.a) && this.x.contains(r.x.b)) { - x_intervals.push([ new vec2( this.x.a, r.x.b ), LEFT ]) - x_intervals.push([ new vec2( r.x.b, this.x.b ), RIGHT ]) - split_contains |= LEFT - } - - else if (this.x.contains(r.x.a) && this.x.contains(r.x.b)) { - x_intervals.push([ new vec2( this.x.a, r.x.a ), LEFT ]) - x_intervals.push([ new vec2( r.x.a, r.x.b ), 0 ]) - x_intervals.push([ new vec2( r.x.b, this.x.b ), RIGHT ]) - split_contains |= LEFT | RIGHT - } - - else { // if (r.x.contains(this.x.a) && r.x.contains(r.x.b)) { - x_intervals.push([ new vec2( this.x.a, this.x.b ), LEFT | RIGHT ]) - split_contains |= LEFT | RIGHT - } - - // Split horizontally - if (this.y.contains(r.y.a) && r.y.contains(this.y.b)) { - y_intervals.push([ new vec2( this.y.a, r.y.a ), FRONT ]) - y_intervals.push([ new vec2( r.y.a, this.y.b ), BACK ]) - split_contains |= BACK - } - - else if (r.y.contains(this.y.a) && this.y.contains(r.y.b)) { - y_intervals.push([ new vec2( this.y.a, r.y.b ), FRONT ]) - y_intervals.push([ new vec2( r.y.b, this.y.b ), BACK ]) - split_contains |= FRONT - } - - else if (this.y.contains(r.y.a) && this.y.contains(r.y.b)) { - y_intervals.push([ new vec2( this.y.a, r.y.a ), FRONT ]) - y_intervals.push([ new vec2( r.y.a, r.y.b ), 0 ]) - y_intervals.push([ new vec2( r.y.b, this.y.b ), BACK ]) - split_contains |= FRONT | BACK - } - - else { // if (r.y.contains(this.y.a) && this.y.contains(r.y.b)) { - y_intervals.push([ new vec2( this.y.a, this.y.b ), FRONT | BACK ]) - split_contains |= FRONT | BACK - } - - x_intervals.forEach(function(x){ - y_intervals.forEach(function(y){ - var rn = new rect(x[0], y[0]) - rn.id = rz.id - rn.sides = ((x[1] | y[1]) & sides) - if (r.intersects(rn)) { - rn.sides = 0 - } - rn.focused = rz.focused - splits.push(rn) - }) - }) - return splits - } - - return rect - -})() diff --git a/assets/javascripts/rectangles/room.js b/assets/javascripts/rectangles/room.js deleted file mode 100644 index 8c9d67d..0000000 --- a/assets/javascripts/rectangles/room.js +++ /dev/null @@ -1,39 +0,0 @@ -window.room = (function(){ - - var room = function(opt){ - this.id = opt.id || clipper.rooms.length - this.rect = opt.rect - this.regions = [] - this.height = opt.height || 200 - this.focused = false - } - - room.prototype.toString = function(){ - return this.rect.toString() - } - - room.prototype.reset = function(){ - var copy = this.rect.clone() - copy.id = this.id - copy.sides = FRONT | BACK | LEFT | RIGHT - this.regions = [ copy ] - } - - room.prototype.clipTo = function(r){ - // for each of this rect's regions split the region if necessary - var regions = this.regions - var splits - - for (var i = 0, len = regions.length; i < len; i++) { - if (regions[i] && regions[i].intersects(r)) { - splits = regions[i].split(r) - regions = regions.concat(splits) - regions[i] = null - } - } - this.regions = regions - } - - return room - -})() diff --git a/assets/javascripts/rectangles/sort.js b/assets/javascripts/rectangles/sort.js deleted file mode 100644 index 8ece95f..0000000 --- a/assets/javascripts/rectangles/sort.js +++ /dev/null @@ -1,37 +0,0 @@ -function sort_rooms_by_position(list){ - return list.sort(function(a,b){ - return compare_rect_position(a.rect, b.rect) - }) -} - -function sort_rects_by_position(list){ - return list.sort(compare_rect_position) -} - -function compare_rect_position(a,b){ - if (a.x.a < b.x.a) { - return -1 - } - if (a.x.a > b.x.a) { - return 1 - } - if (a.y.a < b.y.a) { - return -1 - } - if (a.y.a > b.y.a) { - return 1 - } - return 0 -} - -function sort_rects_by_area(list){ - return list.map(function(r){ return [r.area(), r] }).sort(function(a,b){ - if (a[0] < b[0]) { - return 1 - } - if (a[0] > b[0]) { - return -1 - } - return 0 - }).map(function(r){ return r[1] }) -} diff --git a/assets/javascripts/rectangles/tree.js b/assets/javascripts/rectangles/tree.js deleted file mode 100644 index 577c41a..0000000 --- a/assets/javascripts/rectangles/tree.js +++ /dev/null @@ -1,37 +0,0 @@ -var tree = function(n, data){ - this.lo = null - this.hi = null - this.value = n - this.data = data -} -tree.prototype.find = function(n){ - if (n == this.value) return this - if (n < this.value) return this.lo ? this.lo.find(n) : this - if (n > this.value) return this.hi ? this.hi.find(n) : this -} -tree.prototype.add = function(n, data){ - var closest = this.find(n) - if (n == closest.value) return closest - if (n < closest.value) return closest.lo = new tree(n, data) - if (n > closest.value) return closest.hi = new tree(n, data) -} -tree.prototype.toArray = function(){ - var a = [] - if (this.lo) a = a.concat(this.lo.toArray()) - a.push(this.data) - if (this.hi) a = a.concat(this.hi.toArray()) - return a -} -tree.prototype.toString = function(){ - var s = ""; - if (this.lo) s += this.lo.toString() - s += this.value + "," - if (this.hi) s += this.hi.toString() - return s -} -tree.prototype.depth = function(){ - if (this.lo && this.hi) return 1 + max(this.lo.depth(), this.hi.depth()) - else if (this.lo) return 1 + this.lo.depth() - else if (this.hi) return 1 + this.hi.depth() - else return 0 -} diff --git a/assets/javascripts/rectangles/util/colors.js b/assets/javascripts/rectangles/util/colors.js new file mode 100644 index 0000000..3bdebbc --- /dev/null +++ b/assets/javascripts/rectangles/util/colors.js @@ -0,0 +1,36 @@ +(function(){ + var color_palettes = { + alpha: [ + "rgba(0,0,0,0.1)", + ], + redblue: [ + "rgba(0,0,0,0.2)", + "rgba(255,0,0,0.2)", + "rgba(0,0,255,0.2)", + "rgba(0,255,0,0.2)", + ], + gray: [ + "rgba(0,0,0,0.1)", + "rgba(0,0,0,0.2)", + "rgba(0,0,0,0.3)", + "rgba(0,0,0,0.4)", + ], + colors: [ + "rgba(255,0,0,0.5)", + "rgba(255,128,0,0.5)", + "rgba(128,255,0,0.5)", + "rgba(0,255,0,0.5)", + "rgba(0,255,128,0.5)", + "rgba(0,128,255,0.5)", + "rgba(0,0,255,0.5)", + "rgba(128,0,255,0.5)", + "rgba(255,0,255,0.5)", + "rgba(255,0,128,0.5)", + ] + } + + var select = document.querySelector("#palette") + select.addEventListener("change", function(){ colors = color_palettes[select.value] }) + + window.colors = color_palettes[select.value] +})() diff --git a/assets/javascripts/rectangles/util/debug.js b/assets/javascripts/rectangles/util/debug.js new file mode 100644 index 0000000..437abb8 --- /dev/null +++ b/assets/javascripts/rectangles/util/debug.js @@ -0,0 +1,2 @@ +window.z = true; +document.body.addEventListener("mousedown", function(){ z = true }) diff --git a/assets/javascripts/rectangles/util/mouse.js b/assets/javascripts/rectangles/util/mouse.js new file mode 100644 index 0000000..b8d6045 --- /dev/null +++ b/assets/javascripts/rectangles/util/mouse.js @@ -0,0 +1,114 @@ +/* + usage: + + base.mouse = new mouse({ + el: document.querySelector("#map"), + down: function(e, cursor){ + // do something with val + // cursor.x.a + // cursor.y.a + }, + move: function(e, cursor, delta){ + // delta.a (x) + // delta.b (y) + }, + up: function(e, cursor){ + // cursor.x.a + // cursor.y.a + }, + }) + +*/ + +function mouse (opt) { + var base = this + + opt = defaults(opt, { + el: document, + down: null, + move: null, + drag: null, + up: null, + propagate: false, + locked: false, + val: 0, + }) + + base.down = false + + base.creating = false + base.dragging = false + + base.cursor = new rect(0,0,0,0) + + base.tube = new Tube () + opt.down && base.tube.on("down", opt.down) + opt.move && base.tube.on("move", opt.move) + opt.drag && base.tube.on("drag", opt.drag) + opt.up && base.tube.on("up", opt.up) + + base.init = function (){ + base.bind() + } + + base.bind = function(){ + opt.el.addEventListener("mousedown", base.mousedown) + window.addEventListener("mousemove", base.mousemove) + window.addEventListener("mouseup", base.mouseup) + } + + function positionFromMouse(e) { + var offset = opt.el.getBoundingClientRect() + var mx = offset.left - e.pageX + var my = e.pageY - offset.top + + return new vec2(mx, my) + } + + base.mousedown = function(e){ + e.stopPropagation() + + var pos = positionFromMouse(e) + + var x = pos.a, y = pos.b + base.cursor = new rect (x,y, x,y) + base.down = true + + base.tube("down", e, base.cursor) + } + base.mousemove = function(e){ + e.stopPropagation() + + var pos = positionFromMouse(e) + + if (e.shiftKey) { + pos.quantize(10) + } + + var x = pos.a, y = pos.b + + if (base.down) { + base.cursor.x.b = x + base.cursor.y.b = y + base.tube("drag", e, base.cursor) + } + else { + base.cursor.x.a = base.cursor.x.b = x + base.cursor.y.a = base.cursor.y.b = y + base.tube("move", e, base.cursor) + } + } + base.mouseup = function(e){ + e.stopPropagation() + + if (base.down) { + base.down = false + base.tube("up", e, base.cursor) + var pos = positionFromMouse(e) + base.cursor = new rect(pos.a, pos.b) + } + } + + base.init() +} + diff --git a/assets/javascripts/rectangles/util/sort.js b/assets/javascripts/rectangles/util/sort.js new file mode 100644 index 0000000..8ece95f --- /dev/null +++ b/assets/javascripts/rectangles/util/sort.js @@ -0,0 +1,37 @@ +function sort_rooms_by_position(list){ + return list.sort(function(a,b){ + return compare_rect_position(a.rect, b.rect) + }) +} + +function sort_rects_by_position(list){ + return list.sort(compare_rect_position) +} + +function compare_rect_position(a,b){ + if (a.x.a < b.x.a) { + return -1 + } + if (a.x.a > b.x.a) { + return 1 + } + if (a.y.a < b.y.a) { + return -1 + } + if (a.y.a > b.y.a) { + return 1 + } + return 0 +} + +function sort_rects_by_area(list){ + return list.map(function(r){ return [r.area(), r] }).sort(function(a,b){ + if (a[0] < b[0]) { + return 1 + } + if (a[0] > b[0]) { + return -1 + } + return 0 + }).map(function(r){ return r[1] }) +} diff --git a/assets/javascripts/rectangles/util/wheel.js b/assets/javascripts/rectangles/util/wheel.js new file mode 100644 index 0000000..6836772 --- /dev/null +++ b/assets/javascripts/rectangles/util/wheel.js @@ -0,0 +1,62 @@ +/* + usage: + + base.wheel = new wheel({ + el: document.querySelector("#map"), + update: function(e, val, delta){ + // do something with val + }, + }) + +*/ + +function wheel (opt) { + opt = defaults(opt, { + el: document, + fn: function(e, val, delta){}, + propagate: false, + locked: false, + reversible: true, + ratio: 0.02, + val: 0, + }) + + opt.el.addEventListener('mousewheel', onMouseWheel, false); + opt.el.addEventListener('DOMMouseScroll', onMouseWheel, false); + + function onMouseWheel (e) { + if (opt.locked) { + return + } + if (! opt.propagate) { + e.stopPropagation() + e.preventDefault() + } + + var delta = 0; + + // WebKit + if ( event.wheelDeltaY ) { + delta -= event.wheelDeltaY * opt.ratio + } + // Opera / Explorer 9 + else if ( event.wheelDelta ) { + delta -= event.wheelDelta * opt.ratio + } + // Firefox + else if ( event.detail ) { + delta += event.detail * 2 + } + if (! opt.reversible && delta < 0) return; + + opt.val = clamp(opt.val + delta, opt.min, opt.max) + + opt.update(e, opt.val, delta) + } + + opt.lock = function(){ opt.locked = true } + opt.unlock = function(){ opt.locked = false } + + return opt +} + diff --git a/assets/javascripts/rectangles/vec2.js b/assets/javascripts/rectangles/vec2.js deleted file mode 100644 index 4e2ad36..0000000 --- a/assets/javascripts/rectangles/vec2.js +++ /dev/null @@ -1,81 +0,0 @@ -function vec2(a,b){ - this.a = a - this.b = b -} -vec2.prototype.magnitude = function(){ - return this.b-this.a -} -vec2.prototype.length = function(){ - return abs(this.b-this.a) -} -vec2.prototype.clone = function(){ - return new vec2(this.a, this.b) -} -vec2.prototype.abs = function(){ - if (this.b < this.a) { - this.a = this.a ^ this.b - this.b = this.a ^ this.b - this.a = this.a ^ this.b - } - return this -} -vec2.prototype.midpoint = function(){ - return lerp(0.5, this.a, this.b) -} -vec2.prototype.eq = function(v){ - return this.a == v.a && this.b == v.b -} -vec2.prototype.add = function(n){ - this.a += n - this.b += n -} -vec2.prototype.sub = function(n){ - this.a -= n - this.b -= n -} -vec2.prototype.mul = function(n){ - this.a *= n - this.b *= n -} -vec2.prototype.div = function(n){ - this.a /= n - this.b /= n -} -vec2.normalize = function(){ - var dim = max(this.a, this.b) - this.a = this.a/dim - this.b = this.b/dim -} -vec2.prototype.contains = function(n){ - return this.a <= n && n <= this.b -} -vec2.prototype.intersects = function(v){ - if (this.a < v.a) { - return (v.a < this.b && this.b <= v.b) || (this.a < v.b && v.b <= this.b) - } - else if (this.a == v.a) { - return true - } - else if (this.a > v.a) { - return (this.a < v.b && v.b <= this.b) || (v.a < this.b && this.b <= v.b) - } -} -vec2.prototype.union = function(v){ - if (this.intersects(v)) { - return new vec2( min(this.a,v.a), max(this.b, v.b) ) - } -} -vec2.prototype.intersection = function(v){ - if (this.intersects(v)) { - return new vec2( max(this.a,v.a), min(this.b, v.b) ) - } -} -vec2.prototype.toString = function(){ - return "[" + this.a + " " + this.b + "]" -} -vec2.prototype.quantize = function(n){ - n = n || 10 - this.a = quantize(this.a, n) - this.b = quantize(this.b, n) -} - diff --git a/assets/javascripts/rectangles/wheel.js b/assets/javascripts/rectangles/wheel.js deleted file mode 100644 index cc8dc32..0000000 --- a/assets/javascripts/rectangles/wheel.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - usage: - - base.wheel = new wheel({ - el: document.querySelector("#map"), - update: function(e, val, delta){ - // do something with val - }, - }) - -*/ - -function wheel (opt) { - opt = defaults(opt, { - el: document, - fn: function(e, val, delta){}, - propagate: false, - locked: false, - reversible: true, - ratio: 0.02, - val: 0, - min: -Infinity, - max: Infinity, - }) - - opt.el.addEventListener('mousewheel', onMouseWheel, false); - opt.el.addEventListener('DOMMouseScroll', onMouseWheel, false); - - function onMouseWheel (e) { - if (opt.locked) { - return - } - if (! opt.propagate) { - e.stopPropagation() - e.preventDefault() - } - - var delta = 0; - - // WebKit - if ( event.wheelDeltaY ) { - delta -= event.wheelDeltaY * opt.ratio - } - // Opera / Explorer 9 - else if ( event.wheelDelta ) { - delta -= event.wheelDelta * opt.ratio - } - // Firefox - else if ( event.detail ) { - delta += event.detail * 2 - } - if (! opt.reversible && delta < 0) return; - - opt.val = clamp(opt.val + delta, opt.min, opt.max) - - opt.update(e, opt.val, delta) - } - - opt.lock = function(){ opt.locked = true } - opt.unlock = function(){ opt.locked = false } - - return opt -} - diff --git a/rectangles-canvas-only.html b/rectangles-canvas-only.html index b0c2436..3157a7f 100644 --- a/rectangles-canvas-only.html +++ b/rectangles-canvas-only.html @@ -53,17 +53,20 @@ body > div { - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + -- cgit v1.2.3-70-g09d2