0

So, I'm being a bit creative in searching through persistent graphical objects in HTML5 canvas by using PouchDB and MapRepduce. (I'm trying to tell if the user's clicked on that object with simple bounding box logic) That part isn't all that important; it might be silly, but I just want to do it, because I'm a dork like that.

That said, I want to pass a pair of custom values to the reducer function of my PouchDB query. I'm unsure how to do that, exactly.

Here's kinda what I'm doing right now:

var x = evt.clientX, y = evt.clientY

var map = function (doc) {
  emit('bbox',
    {
      x0: doc.x,
      x1: doc.x + doc.w,
      y0: doc.y,
      y1: doc.y + doc.h
    }
  )
}

var reduce = function (keys, values, rereduce) {
  return values.forEach(function (bbox) {
    if (x >= bbox.x0 && x < bbox.x1 && y >= bbox.y0 && y < bbox.y1) {
      return true
    }
  })
}

var result = db.px.query({map: map, reduce: reduce}, function (err, rsp) {
  cb(rsp)
})

It doesn't work right now because the reduce function can't access the x and y values since, for some reason, they are inaccessible from the scope in which the functions are run. So, I need to pass them to Pouch/Couch through that query method, I think. I'm kinda stuck here.

Hunter Beast
  • 782
  • 7
  • 17

2 Answers2

0

Shouldn't it be sufficient to have a "createReduce" function that makes the x and y parameters more accessible?

var createReduce = function(x,y) { return function(keys, values, rereduce) {...} }
th0br0
  • 1
  • 1
  • 1
    Both the `map` and `reduce` functions are `.toString`'d then `eval`'d to make the emit methods available inside them ([source](https://github.com/daleharvey/pouchdb/blob/master/src/plugins/pouchdb.mapreduce.js#L109-L118)). This throws away any context from where they were originally defined, so this won't work. – jches Nov 09 '13 at 20:51
  • @chesles I guess what I'm trying to do is an impossible thing to do, forever. In that case, I shall make my own clientside database, with blackjack and hookahs. Thank you for your insight. – Hunter Beast Nov 09 '13 at 23:42
  • 1
    @CryptoQuick yeah it doesn't sound like map-reduce is particularly suited to what you're trying to do. But, you might be able to accomplish this with something like leveldb- craft your database keys right and a simple range query might work quite well. Check out [levelup](https://github.com/rvagg/node-levelup) and [level.js](https://github.com/maxogden/level.js) for a browser backend to it. – jches Nov 10 '13 at 13:57
0

It seemed I was trying to do the impossible, and I really didn't need the persistence for this particular application. Furthermore, more complex graphics-oriented spatial queries will require a more specialized data persistence and manipulation framework. I'll be working on such a thing in the future.

That said, here's some helpful filter-based bbox code to help out any intrepid coders out there who might be walking down my own path in the future.

var db = {
  // 2d, canvas-related data store and methods
  px: {
    store: [],
    add: function (obj) {
      db.px.store.push(obj)
    },
    pick: function (x, y) {
      return db.px.store.filter(function (obj) {
        return x >= obj.x
          && x < obj.x + obj.w * gfx.px.ratio
          && y >= obj.y
          && y < obj.y + obj.h * gfx.px.ratio
      })
    }
  }
}

This works over graphical objects formatted like so:

{
  x: 0, y: 0, w: 0, h: 0
}

I hope that's helpful for anyone who tries to do what I'm doing in the future.

Also, the gfx.px.ratio variable is for hi-DPI (retina) display compatibility.

Hunter Beast
  • 782
  • 7
  • 17