Skip to content

Commit

Permalink
Merge pull request #76 from nodetiles/75-customizable-bounds-buffer
Browse files Browse the repository at this point in the history
Customizable buffer sizes for rendered data via `Map.boundsBuffer`.
  • Loading branch information
Mr0grog committed Apr 4, 2014
2 parents b11a15c + 793c4e3 commit f15d4a6
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 11 deletions.
2 changes: 1 addition & 1 deletion LICENSE
@@ -1,4 +1,4 @@
Copyright (c) 2012-2013, Code for America
Copyright (c) 2012-2014, Code for America
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -81,5 +81,5 @@ Projections

Copyright
---------
Copyright (c) 2012-2013 Code for America. See LICENSE for details.
Copyright (c) 2012-2014 Code for America. See LICENSE for details.

41 changes: 33 additions & 8 deletions lib/Map.js
Expand Up @@ -18,25 +18,29 @@ var BUFFER_RATIO = 0.25;
var DEFAULT_PROJECTION = "EPSG:900913";//"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs";

var Map = function(options) {
options = options || {};

this.datasources = [];
this.styles = [];
this.projection = DEFAULT_PROJECTION;
this.assetsPath = ".";

if (options && options.projection){
if (options.projection){
this.projection = projector.util.cleanProjString(options.projection);
console.log(this.projection);
}

this.boundsBuffer =
("boundsBuffer" in options) ? options.boundsBuffer : BUFFER_RATIO;

this._renderer = cartoRenderer;
};

Map.prototype = {
constructor: Map,

render: function(options) {
var bounds = options.bounds;
this._getData(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, function(error, shapes) {
this._getData(options.bounds, options.boundsBuffer, function(error, shapes) {
if (error) {
options.callback(error);
}
Expand All @@ -54,8 +58,7 @@ Map.prototype = {

// Should this really be here, or should it exist on a different object entirely?
renderGrid: function(options) {//minX, minY, maxX, maxY, width, height, asImage, callback) {
var bounds = options.bounds;
this._getData(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, function(error, shapes) {
this._getData(options.bounds, options.boundsBuffer, function(error, shapes) {
if (error) {
options.callback(error);
console.error("ERROR! "+error);
Expand All @@ -73,8 +76,8 @@ Map.prototype = {
}.bind(this));
},

_getData: function(minX, minY, maxX, maxY, callback) {
var buffer = (maxX - minX) * BUFFER_RATIO;
_getData: function(bounds, buffer, callback) {
var dataBounds = this._bufferedBounds(bounds, buffer);

// this is a bit quick and dirty - we could possibly use style data
// to figure out more detailed queries than just geographic bounds
Expand All @@ -96,7 +99,7 @@ Map.prototype = {
}

// allow simple sources to just return results immediately
var syncData = datasource(minX - buffer, minY - buffer, maxX + buffer, maxY + buffer, projection, preCallback);
var syncData = datasource(dataBounds.minX, dataBounds.minY, dataBounds.maxX, dataBounds.maxY, projection, preCallback);
if (syncData) {
preCallback(null, syncData);
}
Expand All @@ -115,6 +118,28 @@ Map.prototype = {
);
},

_bufferedBounds: function(bounds, buffer) {
if (buffer == null) {
buffer = this.boundsBuffer;
}

if (typeof buffer === "function") {
return buffer.call(this, bounds);
}

if (typeof buffer !== "number") {
buffer = BUFFER_RATIO;
}

amount = (bounds.maxX - bounds.minX) * buffer;
return {
minX: bounds.minX - amount,
minY: bounds.minY - amount,
maxX: bounds.maxX + amount,
maxY: bounds.maxY + amount
};
},

addData: function(datasource) {
// validate datasource
if (!(typeof datasource === "function" || typeof datasource.getShapes === "function")) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "nodetiles-core",
"version": "0.0.3",
"version": "0.0.4",
"description": "Joyful map rendering with Node.js.",
"contributors": [
{
Expand Down
111 changes: 111 additions & 0 deletions test/Map.spec.js
@@ -0,0 +1,111 @@
var expect = require("chai").expect;
var sinon = require("sinon");
var Map = require(__dirname + '/../index').Map;

describe("Map", function() {

describe("bounds buffering", function() {

it("should default to 25%", function() {
var data = sinon.stub().returns([]);
var map = new Map();
map.addData(data);
map.addStyle("Map { background-color: #999; }");
map.render({
bounds: {minX: 0, minY: 0, maxX: 10, maxY: 10},
width: 256,
height: 256,
zoom: 10
});
expect(data.calledWith(-2.5, -2.5, 12.5, 12.5)).to.be.true;
});

it("should accept a custom value per map", function() {
var data = sinon.stub().returns([]);
var map = new Map({
boundsBuffer: 0.5
});
map.addData(data);
map.addStyle("Map { background-color: #999; }");
map.render({
bounds: {minX: 0, minY: 0, maxX: 10, maxY: 10},
width: 256,
height: 256,
zoom: 10
});
expect(data.calledWith(-5, -5, 15, 15)).to.be.true;
});

it("should accept a custom function per map", function() {
var data = sinon.stub().returns([]);
var map = new Map({
boundsBuffer: function() {
return {minX: -1, minY: 1, maxX: 12, maxY: 9};
}
});
map.addData(data);
map.addStyle("Map { background-color: #999; }");
map.render({
bounds: {minX: 0, minY: 0, maxX: 10, maxY: 10},
width: 256,
height: 256,
zoom: 10
});
expect(data.calledWith(-1, 1, 12, 9)).to.be.true;
});

it("should accept a custom value per render", function() {
var data = sinon.stub().returns([]);
var map = new Map({
boundsBuffer: 0.5
});
map.addData(data);
map.addStyle("Map { background-color: #999; }");
map.render({
bounds: {minX: 0, minY: 0, maxX: 10, maxY: 10},
width: 256,
height: 256,
zoom: 10,
boundsBuffer: 0.1
});
expect(data.calledWith(-1, -1, 11, 11)).to.be.true;
});

it("should accept a custom function per render", function() {
var data = sinon.stub().returns([]);
var map = new Map({
boundsBuffer: 0.5
});
map.addData(data);
map.addStyle("Map { background-color: #999; }");
map.render({
bounds: {minX: 0, minY: 0, maxX: 10, maxY: 10},
width: 256,
height: 256,
zoom: 10,
boundsBuffer: function() {
return {minX: -1, minY: 1, maxX: 12, maxY: 9};
}
});
expect(data.calledWith(-1, 1, 12, 9)).to.be.true;
});

it("should be able to be 0", function() {
var data = sinon.stub().returns([]);
var map = new Map({
boundsBuffer: 0
});
map.addData(data);
map.addStyle("Map { background-color: #999; }");
map.render({
bounds: {minX: 0, minY: 0, maxX: 10, maxY: 10},
width: 256,
height: 256,
zoom: 10
});
expect(data.calledWith(0, 0, 10, 10)).to.be.true;
});

});

});

0 comments on commit f15d4a6

Please sign in to comment.