From e2e1565f5cd3154c0f515dbe3d88c9943dd0580e Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 4 Aug 2014 17:41:04 -0400 Subject: group walls and render using 'wireframe' look --- .../javascripts/rectangles/engine/rooms/builder.js | 2 +- .../javascripts/rectangles/engine/rooms/grouper.js | 147 +++++++++++++++++++++ .../assets/javascripts/rectangles/models/wall.js | 39 +++--- .../assets/javascripts/rectangles/util/colors.js | 3 +- public/assets/javascripts/rectangles/util/sort.js | 33 ++++- server/index.js | 2 +- test/06-test-grouper.js | 129 +++++++++++++++++- views/partials/scripts.ejs | 1 + 8 files changed, 325 insertions(+), 31 deletions(-) create mode 100644 public/assets/javascripts/rectangles/engine/rooms/grouper.js diff --git a/public/assets/javascripts/rectangles/engine/rooms/builder.js b/public/assets/javascripts/rectangles/engine/rooms/builder.js index 1f21636..6b2e65a 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/builder.js +++ b/public/assets/javascripts/rectangles/engine/rooms/builder.js @@ -43,7 +43,7 @@ if (window.scene) { base.clear() base.build() - Rooms.grouper.group() + Rooms.grouper.build() } } diff --git a/public/assets/javascripts/rectangles/engine/rooms/grouper.js b/public/assets/javascripts/rectangles/engine/rooms/grouper.js new file mode 100644 index 0000000..532146d --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/rooms/grouper.js @@ -0,0 +1,147 @@ +(function(){ + + var Rooms, UidGenerator, Wall, sort + if ('window' in this) { + Rooms = window.Rooms + UidGenerator = window.UidGenerator + Wall = window.Wall + sort = window.sort + } + else { + Rooms = require('./_rooms') + UidGenerator = require('../../util/uid') + Wall = require('../../models/wall') + sort = require('../../util/sort') + FRONT = 0x1, BACK = 0x2, LEFT = 0x4, RIGHT = 0x8, FLOOR = 0x10, CEILING = 0x20 + PI = Math.PI + HALF_PI = PI/2 + TOP = CEILING, BOTTOM = FLOOR + function sidesToString(sides){ + var s = "" + if (sides & FRONT) s += "front " + if (sides & BACK) s += "back " + if (sides & LEFT) s += "left " + if (sides & RIGHT) s += "right " + if (sides & TOP) s += "top " + if (sides & BOTTOM) s += "bottom " + return s + } + } + + Rooms.grouper = new function(){ + + var base = this + + base.list = {} + + base.uid = new UidGenerator(base.list) + + base.build = function (){ + var walls = [] + var collections = base.collect() + base.cull(collections) + base.group(walls, collections, FRONT) + base.group(walls, collections, BACK) + base.group(walls, collections, LEFT) + base.group(walls, collections, RIGHT) + Rooms.walls = walls + base.bind() + } + base.collect = function(){ + var collections = {} + collections[FRONT] = [] + collections[BACK] = [] + collections[LEFT] = [] + collections[RIGHT] = [] + + Rooms.forEach(function(room){ + room.mx_walls.forEach(function(mx){ + var side = mx.side || mx.half_side + collections[side].push(mx) + }) + }) + + base.cull(collections) + + return collections + } + base.cull = function(collections){ + [FRONT, BACK, LEFT, RIGHT].forEach(function(side){ + var collection = collections[side] + var useX = side & FRONT_BACK + var useA = side & (FRONT | RIGHT) + var last_mx + + collection.sort( useX ? sort.compare_zx : sort.compare_xz ) + collection.forEach(function(mx){ + if (last_mx && last_mx.rect.eq(mx.rect)) { +// console.log( mx.y - mx.height/2 ) +// console.log( last_mx.y - last_mx.height/2 ) +// console.log(last_mx.y, mx.y) +// console.log(last_mx.height, mx.height) +// console.log(Rooms.list[ last_mx.rect.id ].height, Rooms.list[ mx.rect.id ].height) +// console.log("___") +// last_mx.height += mx.height/2 +// last_mx.y += mx.height/4 + if (last_mx.rect.id == mx.rect.id) { + last_mx.height += mx.height/2 + last_mx.y += mx.height/4 + } + last_mx.side = side + + mx.culled = true + scene.remove(mx) + return + } + last_mx = mx + }) + }) + return collections + } + base.group = function(walls, collections, side){ + var collection = collections[side] + var wall + var useX = side & FRONT_BACK + var useA = side & (FRONT | RIGHT) + + // collection.sort( useX ? sort.compare_zx : sort.compare_xz ) + + collection.forEach(function(mx){ + if (mx.culled) return + var coplanar = wall && wall.edge == mx.rect[useX ? 'y': 'x'][useA ? 'a': 'b'] + + if (wall && coplanar) { + if (useX && wall.vec.b == mx.rect.x.a) { + wall.vec.b = mx.rect.x.b + wall.mx.push(mx) + return + } + else if (! useX && wall.vec.b == mx.rect.y.a) { + wall.vec.b = mx.rect.y.b + wall.mx.push(mx) + return + } + } + wall = new Wall ({ + id: base.uid(), + side: side, + vec: mx.rect[ useX ? 'x' : 'y' ].clone(), + edge: mx.rect[useX ? 'y' : 'x' ][ useA ? 'a' : 'b' ], + el: mx, + }) + walls.push(wall) + }) + + return walls + } + + base.bind = function(){ + Rooms.walls.forEach(function(wall){ + wall.bind() + wall.randomize_colors() + }) + } + + } + +})() diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index f2b8bca..41d7235 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -17,6 +17,7 @@ this.id = opt.id this.uid = wall_uid this.vec = opt.vec + this.edge = opt.edge this.side = opt.side this.mx = [] if (opt.el) { @@ -148,20 +149,18 @@ var ctx = canvas.getContext('2d') var useX = this.side & FRONT_BACK var shouldFlip = this.side & (LEFT | BACK) + var mx = this.mx - var sortedWalls = this.siblings().reduce(function(a,w){ - return a.concat(w.mx) - }, []).sort( useX ? sort.compare_x : sort.compare_z ) - - if (shouldFlip) { - sortedWalls = sortedWalls.reverse() + // console.log( sidesToString(this.side), mx.length ) + if (! shouldFlip) { + mx = mx.reverse() } - var len = sortedWalls.length + var len = this.mx.length zz = window.zz || 0 - sortedWalls.forEach(function(mx, i){ + mx.forEach(function(mx, i){ if (mx.outlined) return mx.outlined = true canvas.width = mx.width @@ -170,10 +169,10 @@ ctx.fillRect(0, 0, canvas.width, canvas.height) ctx.fillStyle = "rgba(0,0,0,1.0)" - // all walls except top-half walls get bottom lines + // all walls get bottom lines ctx.fillRect(0, 0, canvas.width, 1) - // all walls except bottom-half walls get top lines + // all walls get top lines ctx.fillRect(0, canvas.height-1, canvas.width, 1) // walls on initial sides get left lines @@ -185,7 +184,6 @@ // walls on terminal sides get right lines.... // if their right edge lines up with the rect edge if (i == len-1) { - // ctx.fillStyle = "rgba(255,0,0,1.0)" ctx.fillRect(canvas.width-1, 0, 1, canvas.height) } var dataUrl = canvas.toDataURL() @@ -195,21 +193,18 @@ } Wall.prototype.siblings = function(){ - var base = this - var match = base.side | base.half_side - var walls = Rooms.list[this.room].walls.filter(function(w){ - return (w.side | w.half_side) & match && w.$walls - }) - return walls + return this +// var base = this +// var match = base.side | base.half_side +// var walls = Rooms.list[this.room].walls.filter(function(w){ +// return (w.side | w.half_side) & match && w.$walls +// }) +// return walls } Wall.prototype.randomize_colors = function(){ var color = window.grayColors[ this.side | this.half_side ] - var siblings = this.siblings() - siblings.forEach(function(w, i){ - if (! w.$walls) return - w.color(color) - }) + this.color(color) } Wall.prototype.stroke_colors = function(){ diff --git a/public/assets/javascripts/rectangles/util/colors.js b/public/assets/javascripts/rectangles/util/colors.js index 95827cc..16d34dd 100644 --- a/public/assets/javascripts/rectangles/util/colors.js +++ b/public/assets/javascripts/rectangles/util/colors.js @@ -58,7 +58,8 @@ select.blur() }) - window.colors = color_palettes[select ? select.value : 'alphaQuad'] + window.colors = color_palettes[select ? select.value : 'colors'] +// window.colors = color_palettes[select ? select.value : 'alphaQuad'] window.grayColors = {} _.zip([FRONT, LEFT, BACK, RIGHT], color_palettes.alphaQuad).map(function(pair){ window.grayColors[pair[0]] = pair[1] diff --git a/public/assets/javascripts/rectangles/util/sort.js b/public/assets/javascripts/rectangles/util/sort.js index 7aa40a2..cf8d6b1 100644 --- a/public/assets/javascripts/rectangles/util/sort.js +++ b/public/assets/javascripts/rectangles/util/sort.js @@ -95,9 +95,38 @@ return a.x < b.x ? -1 : a.x == b.x ? 0 : 1 } sort.compare_z = function (a,b){ - return a.z > b.z ? -1 : a.z == b.z ? 0 : 1 + return a.z < b.z ? -1 : a.z == b.z ? 0 : 1 } - + sort.compare_xz = function(a,b){ + if (a.x < b.x) { + return -1 + } + if (a.x > b.x) { + return 1 + } + if (a.z < b.z) { + return -1 + } + if (a.z > b.z) { + return 1 + } + return 0 + } + sort.compare_zx = function(a,b){ + if (a.z < b.z) { + return -1 + } + if (a.z > b.z) { + return 1 + } + if (a.x < b.x) { + return -1 + } + if (a.x > b.x) { + return 1 + } + return 0 + } if ("window" in this) { window.sort = sort } diff --git a/server/index.js b/server/index.js index 71cd862..ad437ff 100644 --- a/server/index.js +++ b/server/index.js @@ -50,7 +50,7 @@ site.setup = function(){ app.use(express.session({ key: 'vvalls.sid', secret: 'flibbertigibbet', - cookie: { domain: '.' + config.hostName, maxAge: 432000000 }, + cookie: { domain: '.' + config.hostName, maxAge: 43200000000 }, store: SessionStore })); app.use(bodyParser()); diff --git a/test/06-test-grouper.js b/test/06-test-grouper.js index 1707e4c..41ed0b0 100644 --- a/test/06-test-grouper.js +++ b/test/06-test-grouper.js @@ -29,10 +29,12 @@ var east = new Rect( new vec(2,6), new vec(1,5) ) var corner = new Rect( new vec(3,7), new vec(3,7) ) var peninsula = new Rect( new vec(4,6), new vec(6,8) ) -var rect_room = new Room({ id: "rect", rect: rect, height: 2 }) -var east_room = new Room({ id: "east", rect: east, height: 2 }) -var corner_room = new Room({ id: "corner", rect: corner, height: 2 }) -var peninsula_room = new Room({ id: "peninsula", rect: peninsula, height: 2 }) +var rect_room = new Room({ id: "rect", rect: rect, height: 2 }) +var east_room = new Room({ id: "east", rect: east, height: 2 }) +var corner_room = new Room({ id: "corner", rect: corner, height: 2 }) +var peninsula_room = new Room({ id: "peninsula", rect: peninsula, height: 2 }) +var peninsula_taller = new Room({ id: "peninsula", rect: peninsula, height: 3 }) +var peninsula_shorter = new Room({ id: "peninsula", rect: peninsula, height: 1 }) var taller_room = new Room({ id: "taller", rect: rect, height: 3 }) @@ -118,4 +120,123 @@ describe('grouper(rect,east)', function(){ }) }) +describe('grouper(rect,corner)', function(){ + reset() + Rooms.add( rect_room ) + Rooms.add( corner_room ) + rebuild() + + var collections = Rooms.grouper.collect() + + describe('#group(rect,corner)', function(){ + var front_walls = Rooms.grouper.group([], collections, FRONT) + var back_walls = Rooms.grouper.group([], collections, BACK) + var left_walls = Rooms.grouper.group([], collections, LEFT) + var right_walls = Rooms.grouper.group([], collections, RIGHT) + + it("left has 2 walls", function(){ + assert.equal(2, left_walls.length) + }) + it("right has 2 walls", function(){ + assert.equal(2, right_walls.length) + }) + it("front has 2 walls", function(){ + assert.equal(2, front_walls.length) + }) + it("back has 2 walls", function(){ + assert.equal(2, back_walls.length) + }) + it("front/right walls are one narrow, one wide", function(){ + assert.equal(4, front_walls[0].vec.length()) + assert.equal(2, front_walls[1].vec.length()) + assert.equal(2, right_walls[0].vec.length()) + assert.equal(4, right_walls[1].vec.length()) + }) + it("back/left walls are one wide, one narrow", function(){ + assert.equal(2, back_walls[0].vec.length()) + assert.equal(4, back_walls[1].vec.length()) + assert.equal(4, left_walls[0].vec.length()) + assert.equal(2, left_walls[1].vec.length()) + }) + }) +}) + +describe('grouper(rect,corner,peninsula)', function(){ + reset() + Rooms.add( rect_room ) + Rooms.add( corner_room ) + Rooms.add( peninsula_room ) + rebuild() + + var collections = Rooms.grouper.collect() + + describe('#collect(rect,corner,peninsula)', function(){ + it("should find an appropriate number of wall segments", function(){ + assert.equal(3, collections[FRONT].length) + assert.equal(4, collections[BACK].length) + assert.equal(5, collections[LEFT].length) + assert.equal(5, collections[RIGHT].length) + }) + }) + + describe('#group(rect,corner,peninsula)', function(){ + var front_walls = Rooms.grouper.group([], collections, FRONT) + var back_walls = Rooms.grouper.group([], collections, BACK) + var left_walls = Rooms.grouper.group([], collections, LEFT) + var right_walls = Rooms.grouper.group([], collections, RIGHT) + + it("left has 3 walls", function(){ + assert.equal(3, left_walls.length) + }) + it("right has 4 walls", function(){ + assert.equal(4, right_walls.length) + }) + it("front has 2 walls", function(){ + assert.equal(2, front_walls.length) + }) + it("back has 4 walls", function(){ + assert.equal(4, back_walls.length) + }) + }) +}) + + +describe('grouper(rect,corner,peninsula_taller)', function(){ + reset() + Rooms.add( rect_room ) + Rooms.add( corner_room ) + Rooms.add( peninsula_taller ) + rebuild() + + var collections = Rooms.grouper.collect() + + describe('#collect(rect,corner,peninsula_taller)', function(){ + it("should find an appropriate number of wall segments", function(){ + assert.equal(5, collections[FRONT].length) + assert.equal(4, collections[BACK].length) + assert.equal(6, collections[LEFT].length) + assert.equal(6, collections[RIGHT].length) + }) + }) + + describe('#group(rect,corner,peninsula_taller)', function(){ + var front_walls = Rooms.grouper.group([], collections, FRONT) + var back_walls = Rooms.grouper.group([], collections, BACK) + var left_walls = Rooms.grouper.group([], collections, LEFT) + var right_walls = Rooms.grouper.group([], collections, RIGHT) + + it("left has 4 walls", function(){ + assert.equal(4, left_walls.length) + }) + it("right has 5 walls", function(){ + assert.equal(5, right_walls.length) + }) + it("front has 3 walls", function(){ + assert.equal(3, front_walls.length) + }) + it("back has 4 walls", function(){ + assert.equal(4, back_walls.length) + }) + }) +}) diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 0133ad0..915027d 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -38,6 +38,7 @@ + -- cgit v1.2.3-70-g09d2