summaryrefslogtreecommitdiff
path: root/public/assets/javascripts/rectangles/models
diff options
context:
space:
mode:
Diffstat (limited to 'public/assets/javascripts/rectangles/models')
-rw-r--r--public/assets/javascripts/rectangles/models/rect.js118
-rw-r--r--public/assets/javascripts/rectangles/models/room.js49
-rw-r--r--public/assets/javascripts/rectangles/models/tree.js85
-rw-r--r--public/assets/javascripts/rectangles/models/vec2.js89
4 files changed, 230 insertions, 111 deletions
diff --git a/public/assets/javascripts/rectangles/models/rect.js b/public/assets/javascripts/rectangles/models/rect.js
index 315adef..590440a 100644
--- a/public/assets/javascripts/rectangles/models/rect.js
+++ b/public/assets/javascripts/rectangles/models/rect.js
@@ -1,5 +1,25 @@
(function(){
+ var vec2
+ if ('window' in this) {
+ vec2 = window.vec2
+ }
+ else {
+ vec2 = require('./vec2')
+ FRONT = 0x1, BACK = 0x2, LEFT = 0x4, RIGHT = 0x8, FLOOR = 0x10, CEILING = 0x20
+ 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
+ }
+ }
+
var Rect = function (x0,y0,x1,y1){
if (x0 instanceof vec2) {
this.x = x0
@@ -74,8 +94,18 @@
Rect.prototype.containsDisc = function(x,y,r){
return this.x.containsDisc(x,r) && this.y.containsDisc(y,r)
}
+ Rect.prototype.overlaps = function(rect){
+ return this.x.overlaps(rect.x) && this.y.overlaps(rect.y)
+ }
Rect.prototype.intersects = function(r){
- return this.x.intersects(r.x) && this.y.intersects(r.y)
+ var corner_intersect = (this.x.b === r.x.a && this.y.b === r.y.a)
+ return this.x.intersects(r.x) && this.y.intersects(r.y) && ! corner_intersect
+ }
+ Rect.prototype.adjacent = function(r){
+ return this.x.adjacent(r.x) && this.y.adjacent(r.y)
+ }
+ Rect.prototype.eq = function(r){
+ return this.x.eq(r.x) && this.y.eq(r.y)
}
Rect.prototype.nearEdge = function (x, y, r) {
var edges = 0
@@ -111,79 +141,51 @@
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
- }
+ // bisect (or trisect) two overlapping rectangles
+ var x_intervals = this.x.split( r.x, LEFT, RIGHT )
+ var y_intervals = this.y.split( r.y, FRONT, BACK )
- x_intervals.forEach(function(x){
- y_intervals.forEach(function(y){
+ // generate rectangular regions by crossing the two sets of vectors
+ x_intervals.forEach(function(x, i){
+ y_intervals.forEach(function(y, i){
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)
+
+ // cull extra walls from overlapping regions
+ if (r.x.contains(rn.x.a) && r.x.contains(rn.x.b)) {
+ if (rz.y.a == rn.y.a && r.y.containsCenter(rn.y.a)) { // top edges
+ rn.sides &= ~ FRONT
+ }
+ if (rz.y.b == rn.y.b && r.y.containsCenter(rn.y.b)) { // bottom edges
+ rn.sides &= ~ BACK
+ }
+ }
+
+ if (r.y.contains(rn.y.a) && r.y.contains(rn.y.b)) {
+ if (rz.x.a == rn.x.a && r.x.containsCenter(rn.x.a)) { // left edges
+ rn.sides &= ~ LEFT
+ }
+
+ if (rz.x.b == rn.x.b && r.x.containsCenter(rn.x.b) ) { // right edges
+ rn.sides &= ~ RIGHT
+ }
+ }
+
})
})
+
return splits
}
if ('window' in this) {
window.Rect = Rect
}
- else if ('module' in this) {
+ else {
module.exports = Rect
}
diff --git a/public/assets/javascripts/rectangles/models/room.js b/public/assets/javascripts/rectangles/models/room.js
index 61a7447..d19ca2f 100644
--- a/public/assets/javascripts/rectangles/models/room.js
+++ b/public/assets/javascripts/rectangles/models/room.js
@@ -1,4 +1,32 @@
-window.Room = (function(){
+
+(function(){
+ var vec2, Rect, sort
+ if ('window' in this) {
+ vec2 = window.vec2
+ Rect = window.Rect
+ sort = window.sort
+ }
+ else {
+ vec2 = require('./vec2')
+ Rect = require('./rect')
+ UidGenerator = require('../util/uid')
+ Rooms = { uid: new UidGenerator({}) }
+ sort = require('../util/sort')
+ FRONT = 0x1, BACK = 0x2, LEFT = 0x4, RIGHT = 0x8, FLOOR = 0x10, CEILING = 0x20
+ TOP = CEILING, BOTTOM = FLOOR
+ FRONT_BACK = FRONT | BACK
+ LEFT_RIGHT = LEFT | RIGHT
+ 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
+ }
+ }
var Room = function(opt){
this.id = opt.id || Rooms.uid("room_")
@@ -81,10 +109,10 @@ window.Room = (function(){
var side = pair[0], els = pair[1]
if (side & LEFT_RIGHT) {
- els.sort(compare_x)
+ els.sort(sort.compare_x)
}
else if (side & FRONT_BACK) {
- els.sort(compare_z)
+ els.sort(sort.compare_z)
}
// wall holds state for the last wall we created/saw..
@@ -212,17 +240,22 @@ window.Room = (function(){
if (contains_x) {
collision |= wall_collision & FRONT_BACK
}
- else if (contains_y) {
+ if (contains_y) {
collision |= wall_collision & LEFT_RIGHT
}
- else if (bitcount(wall_collision) > 1) {
- collision |= wall_collision
- }
+// if (bitcount(wall_collision) > 1) {
+// collision |= wall_collision
+// }
})
return collision
}
- return Room
+ if ('window' in this) {
+ window.Room = Room
+ }
+ else {
+ module.exports = Room
+ }
})()
diff --git a/public/assets/javascripts/rectangles/models/tree.js b/public/assets/javascripts/rectangles/models/tree.js
index 8193988..7c698fe 100644
--- a/public/assets/javascripts/rectangles/models/tree.js
+++ b/public/assets/javascripts/rectangles/models/tree.js
@@ -1,37 +1,48 @@
-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
-}
+(function(){
+
+ 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
+ }
+
+ if ('window' in this) {
+ window.Tree = Tree
+ }
+ else {
+ module.exports = Tree
+ }
+
+})()
diff --git a/public/assets/javascripts/rectangles/models/vec2.js b/public/assets/javascripts/rectangles/models/vec2.js
index 9233aec..2bf286b 100644
--- a/public/assets/javascripts/rectangles/models/vec2.js
+++ b/public/assets/javascripts/rectangles/models/vec2.js
@@ -1,4 +1,6 @@
(function(){
+ function clamp(n,a,b){ return n<a?a:n<b?n:b }
+
var vec2 = function (a,b){
this.a = a
this.b = b
@@ -7,7 +9,7 @@
return this.b-this.a
}
vec2.prototype.length = function(){
- return abs(this.b-this.a)
+ return Math.abs(this.b-this.a)
}
vec2.prototype.dist = function(){
return dist(0,this.a,0,this.b)
@@ -70,6 +72,9 @@
vec2.prototype.contains = function(n){
return this.a <= n && n <= this.b
}
+ vec2.prototype.containsCenter = function(n){
+ return this.a < n && n < this.b
+ }
vec2.prototype.containsDisc = function(n,r){
return this.a <= n-r && n+r <= this.b
}
@@ -80,16 +85,35 @@
return clamp(n, this.a+r, this.b-r)
}
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) {
+ if (this.a == v.a || this.b == v.b || this.a == v.b || this.b == v.a) {
return true
}
+ else 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 (this.a < v.b && v.b <= this.b) || (v.a < this.b && this.b <= v.b)
}
}
+ vec2.prototype.overlaps = function(v){
+ if (this.a == v.a || this.b == v.b) {
+ return true
+ }
+ if (this.a < v.a) {
+ return (v.a < this.b && this.b < v.b) || (this.a < v.b && v.b < this.b)
+ }
+ else if (v.a < this.a) {
+ return (this.a < v.b && v.b < this.b) || (v.a < this.b && this.b < v.b)
+ }
+ }
+
+
+ vec2.prototype.adjacent = function(v){
+ if (this.a == v.a || this.b == v.b || this.a == v.b || this.b == v.a) {
+ return true
+ }
+ return false
+ }
vec2.prototype.union = function(v){
if (this.intersects(v)) {
return new vec2( min(this.a,v.a), max(this.b, v.b) )
@@ -100,6 +124,56 @@
return new vec2( max(this.a,v.a), min(this.b, v.b) )
}
}
+
+ // given two vectors, test how they overlap
+ // return the set of overlapping segments in the initial vector, labelled with sides
+ vec2.prototype.split = function(v, left, right){
+ var intervals = [], _len
+
+ if (this.eq(v)) {
+ intervals.push([ new vec2( this.a, this.b ), left | right ])
+ }
+
+ // a---A===b---B (rightways overlap)
+ else if (this.contains(v.a) && v.contains(this.b)) {
+ intervals.push([ new vec2( this.a, v.a ), left ])
+ intervals.push([ new vec2( v.a, this.b ), right ])
+ }
+
+ // A---a===B---b (leftways overlap)
+ else if (v.contains(this.a) && this.contains(v.b)) {
+ intervals.push([ new vec2( this.a, v.b ), left ])
+ intervals.push([ new vec2( v.b, this.b ), right ])
+ }
+
+ // a---A===B---b (contains v)
+ else if (this.contains(v.a) && this.contains(v.b)) {
+ intervals.push([ new vec2( this.a, v.a ), left ])
+ intervals.push([ new vec2( v.a, v.b ), 0 ])
+ intervals.push([ new vec2( v.b, this.b ), right ])
+ }
+
+ // A---a===b---B (contained in v)
+ else { // if (v.contains(this.a) && v.contains(v.b)) {
+ intervals.push([ new vec2( this.a, this.b ), left | right ])
+ }
+
+ // cull empty vectors
+ _len = intervals.length
+ if (_len > 1) {
+ if (intervals[0][0].magnitude() == 0) {
+ intervals[1][1] |= intervals[0][1]
+ intervals.shift()
+ }
+ else if (intervals[_len-1][0].magnitude() == 0) {
+ intervals[_len-2][1] |= intervals[_len-1][1]
+ intervals.pop()
+ }
+ }
+
+ return intervals
+ }
+
vec2.prototype.toString = function(){
return "[" + ~~this.a + " " + ~~this.b + "]"
}
@@ -115,8 +189,7 @@
if ('window' in this) {
window.vec2 = vec2
}
- else if ('module' in this) {
+ else {
module.exports = vec2
}
-
-})() \ No newline at end of file
+})()