node-red-contrib-leap-motion
Version:
Node-Red nodes for leap motion
87 lines (78 loc) • 2.57 kB
JavaScript
var EventEmitter = require('events').EventEmitter
, _ = require('underscore')
var Region = module.exports = function(start, end) {
this.start = new Vector(start)
this.end = new Vector(end)
this.enteredFrame = null
}
Region.prototype.hasPointables = function(frame) {
for (var i = 0; i != frame.pointables.length; i++) {
var position = frame.pointables[i].tipPosition
if (position.x >= this.start.x && position.x <= this.end.x && position.y >= this.start.y && position.y <= this.end.y && position.z >= this.start.z && position.z <= this.end.z) {
return true
}
}
return false
}
Region.prototype.listener = function(opts) {
var region = this
if (opts && opts.nearThreshold) this.setupNearRegion(opts.nearThreshold)
return function(frame) {
return region.updatePosition(frame)
}
}
Region.prototype.clipper = function() {
var region = this
return function(frame) {
region.updatePosition(frame)
return region.enteredFrame ? frame : null
}
}
Region.prototype.setupNearRegion = function(distance) {
var nearRegion = this.nearRegion = new Region(
[this.start.x - distance, this.start.y - distance, this.start.z - distance],
[this.end.x + distance, this.end.y + distance, this.end.z + distance]
)
var region = this
nearRegion.on("enter", function(frame) {
region.emit("near", frame)
})
nearRegion.on("exit", function(frame) {
region.emit("far", frame)
})
region.on('exit', function(frame) {
region.emit("near", frame)
})
}
Region.prototype.updatePosition = function(frame) {
if (this.nearRegion) this.nearRegion.updatePosition(frame)
if (this.hasPointables(frame) && this.enteredFrame == null) {
this.enteredFrame = frame
this.emit("enter", this.enteredFrame)
} else if (!this.hasPointables(frame) && this.enteredFrame != null) {
this.enteredFrame = null
this.emit("exit", this.enteredFrame)
}
return frame
}
Region.prototype.normalize = function(position) {
return new Vector([
(position.x - this.start.x) / (this.end.x - this.start.x),
(position.y - this.start.y) / (this.end.y - this.start.y),
(position.z - this.start.z) / (this.end.z - this.start.z)
])
}
Region.prototype.mapToXY = function(position, width, height) {
var normalized = this.normalize(position)
var x = normalized.x, y = normalized.y
if (x > 1) x = 1
else if (x < -1) x = -1
if (y > 1) y = 1
else if (y < -1) y = -1
return [
(x + 1) / 2 * width,
(1 - y) / 2 * height,
normalized.z
]
}
_.extend(Region.prototype, EventEmitter.prototype)