diff --git a/README.md b/README.md
index 91ea5f5..f462eca 100644
--- a/README.md
+++ b/README.md
@@ -24,13 +24,13 @@ Once you have the couchapp utility working, git clone this repo and
### [Spatial Views](https://github.com/couchbase/geocouch)
-#### points.js
+#### basic.js
A spatial view that additionally emits the original GeoJSON value (doc.geometry)
Example:
- $ curl 'http://localhost:5984/yourdb/_design/geo/_spatial/points?bbox=80,88,90,90'
+ $ curl 'http://localhost:5984/yourdb/_design/geo/_spatial/basic?bbox=80,88,90,90'
{
"update_seq":203,
"rows":[
@@ -56,13 +56,13 @@ Example:
]
}
-#### pointsFull.js
+#### full.js
-A spatial view that emits both GeoJSON and the full document (as value).
+A spatial view that emits both GeoJSON and the full document (as value).
Example:
- $ curl 'http://localhost:5984/yourdb/_design/geo/_spatial/pointsFull?bbox=80,88,90,90'
+ $ curl 'http://localhost:5984/yourdb/_design/geo/_spatial/full?bbox=80,88,90,90'
{
"update_seq":203,
"rows":[
@@ -89,13 +89,13 @@ Example:
]
}
-#### pointsOnly.js
+#### minimal.js
A spatial view that only emits GeoJSON and no additional value.
Example:
- $ curl 'http://localhost:5984/yourdb/_design/geo/_spatial/pointsOnly?bbox=80,88,90,90'
+ $ curl 'http://localhost:5984/yourdb/_design/geo/_spatial/minimal?bbox=80,88,90,90'
{
"update_seq":203,
"rows":[
@@ -178,7 +178,7 @@ This list function generates a simple KML feed
Example:
- $ curl http://localhost:5984/yourdb/_design/geo/_spatiallist/kml/points?bbox=0,0,45,45
+ $ curl http://localhost:5984/yourdb/_design/geo/_spatial/_list/kml/basic?bbox=0,0,45,45
@@ -198,7 +198,7 @@ This function outputs a GeoJSON FeatureCollection (compatible with OpenLayers).
Example:
- $curl -X GET 'http://localhost:5984/yourdb/_design/geo/_spatiallist/geojson/points?bbox=80,88,90,90'
+ $ curl 'http://localhost:5984/yourdb/_design/geo/_spatial/_list/geojson/basic?bbox=80,88,90,90'
{
"type":"FeatureCollection",
"features":[
@@ -223,11 +223,9 @@ Example:
This will take the centroid of the bbox parameter and a supplied radius parameter in meters and filter the rectangularly shaped bounding box result set by circular radius.
-**WARNING** This only works with on points, not lines or polygons yet
-
Example:
- $ curl -X GET http://localhost:5984/yourdb/_design/geo/_spatiallist/radius/points?bbox=-122.67,45.52,-122.67,45.52&radius=50
+ $ curl 'http://localhost:5984/yourdb/_design/geo/_spatial/_list/radius/basic?bbox=-122.67,45.52,-122.67,45.52&radius=50'
{
"type":"FeatureCollection",
"features":[
diff --git a/couchapp/_attachments/script/geojson-utils.js b/couchapp/_attachments/script/geojson-utils.js
index 5f1e671..3fbf393 100755
--- a/couchapp/_attachments/script/geojson-utils.js
+++ b/couchapp/_attachments/script/geojson-utils.js
@@ -139,6 +139,30 @@
return { 'type': 'Point', 'coordinates': [y/f, x/f] };
},
+ // checks if geometry lies entirely within a circle
+ // works with Point, LineString, Polygon
+ gju.geometryWithinRadius = function (geometry, center, radius) {
+ if (geometry.type == 'Point') {
+ return gju.pointDistance(geometry, center) <= radius;
+ } else if (geometry.type == 'LineString' || geometry.type == 'Polygon') {
+ var point = {};
+ var coordinates;
+ if (geometry.type == 'Polygon') {
+ // it's enough to check the exterior ring of the Polygon
+ coordinates = geometry.coordinates[0];
+ } else {
+ coordinates = geometry.coordinates;
+ }
+ for (var i in coordinates) {
+ point.coordinates = coordinates[i];
+ if (gju.pointDistance(point, center) > radius) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
gju.simplify = function (source, kink) {
/* source[] array of geojson points */
/* kink in metres, kinks above this depth kept */
diff --git a/couchapp/lists/radius.js b/couchapp/lists/radius.js
index 032c01e..dc4bbc6 100755
--- a/couchapp/lists/radius.js
+++ b/couchapp/lists/radius.js
@@ -16,7 +16,6 @@ function(head, req) {
"coordinates": [[[bbox[0], bbox[1]], [bbox[2], bbox[3]]]]
}),
callback = req.query.callback,
- circle = gju.drawCircle(radius, center),
startedOutput = false;
if (req.headers.Accept.indexOf('application/json') != -1)
@@ -27,7 +26,7 @@ function(head, req) {
if ('callback' in req.query) send(req.query['callback'] + "(");
send('{"type": "FeatureCollection", "features":[');
while (row = getRow()) {
- if (gju.pointInPolygon(row.value.geometry, circle)) {
+ if (gju.geometryWithinRadius(row.value.geometry, center, radius)) {
if (startedOutput) send(",\n");
out = '{"type": "Feature", "geometry": ' + JSON.stringify(row.value.geometry);
delete row.value.geometry;
diff --git a/couchapp/rewrites.json b/couchapp/rewrites.json
index bd21df1..16e96b1 100644
--- a/couchapp/rewrites.json
+++ b/couchapp/rewrites.json
@@ -20,7 +20,7 @@
"from": ""
},
{
- "to": "/_spatiallist/geojson/full",
+ "to": "/_spatial/_list/geojson/full",
"from": "/data"
},
{
diff --git a/couchapp/vendor/geojson-utils.js b/couchapp/vendor/geojson-utils.js
index 5f1e671..3fbf393 100644
--- a/couchapp/vendor/geojson-utils.js
+++ b/couchapp/vendor/geojson-utils.js
@@ -139,6 +139,30 @@
return { 'type': 'Point', 'coordinates': [y/f, x/f] };
},
+ // checks if geometry lies entirely within a circle
+ // works with Point, LineString, Polygon
+ gju.geometryWithinRadius = function (geometry, center, radius) {
+ if (geometry.type == 'Point') {
+ return gju.pointDistance(geometry, center) <= radius;
+ } else if (geometry.type == 'LineString' || geometry.type == 'Polygon') {
+ var point = {};
+ var coordinates;
+ if (geometry.type == 'Polygon') {
+ // it's enough to check the exterior ring of the Polygon
+ coordinates = geometry.coordinates[0];
+ } else {
+ coordinates = geometry.coordinates;
+ }
+ for (var i in coordinates) {
+ point.coordinates = coordinates[i];
+ if (gju.pointDistance(point, center) > radius) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
gju.simplify = function (source, kink) {
/* source[] array of geojson points */
/* kink in metres, kinks above this depth kept */
diff --git a/misc/geocouch-filler-js/geocouch-filler.js b/misc/geocouch-filler-js/geocouch-filler.js
index eff0c40..f8809de 100644
--- a/misc/geocouch-filler-js/geocouch-filler.js
+++ b/misc/geocouch-filler-js/geocouch-filler.js
@@ -6,71 +6,69 @@
var http = require('http');
var url = require('url');
var path = require('path');
-
-require.paths.unshift(path.join(__dirname, 'lib'));
var Barrier = require('barrier').Barrier;
var httpClientPoolSize = 16;
-var host,port,db;
+var host, port, db;
-if(process.argv.length < 5){
- console.log("\n\tUsage: node geocouch-filler.js <[bbox]> \n\n")
- process.exit(1);
+if (process.argv.length < 5) {
+ console.log("\n\tUsage: node geocouch-filler.js <[bbox]> \n\n")
+ process.exit(1);
};
var uri = url.parse(process.argv[2] || "http://localhost:5984/gc-utils");
-var bbox = JSON.parse(process.argv[3] || "[-180,-90,180,90]") ;
+var bbox = JSON.parse(process.argv[3] || "[-180,-90,180,90]");
var documentCount = parseInt(process.argv[4]) || 10;
-if(uri && bbox && bbox.length === 4 && documentCount){
- host = uri.hostname;
- port = uri.port || 5984;
- db = uri.pathname.split("/")[1] || "gc-utils";
+if (uri && bbox && bbox.length === 4 && documentCount) {
+ host = uri.hostname;
+ port = uri.port || 5984;
+ db = uri.pathname.split("/")[1] || "gc-utils";
}
-var randomArbitrary = function(min, max) {
+var randomArbitrary = function (min, max) {
return Math.random() * (max - min) + min;
-};
+ };
//create client pool to speed
var clients = [];
for (var i = 0; i < httpClientPoolSize; i++) {
- clients.push(http.createClient(port, host));
+ clients.push(http.createClient(port, host));
}
//barrier allows to exit when queries have been executed
-var b = new Barrier(documentCount, function() {
- console.log("Insertion completed");
- process.exit(0);
+var b = new Barrier(documentCount, function () {
+ console.log("Insertion completed");
+ process.exit(0);
});
var ptr = 0;
for (var i = 0; i < documentCount; i++) {
- var client = clients[ptr++ % httpClientPoolSize];
+ var client = clients[ptr++ % httpClientPoolSize];
- var entity = {
- "geometry" : {
- "type" : "Point",
- "coordinates": [randomArbitrary(bbox[0],bbox[2]),randomArbitrary(bbox[1],bbox[3])]
- }
- };
+ var entity = {
+ "geometry": {
+ "type": "Point",
+ "coordinates": [randomArbitrary(bbox[0], bbox[2]), randomArbitrary(bbox[1], bbox[3])]
+ }
+ };
- var request = client.request('POST', "/" + db, {
- "Content-Type": "application/json",
- "Connection": "keep-alive"
- });
- request.write(JSON.stringify(entity));
- request.end();
- request.once('response', function (response) {
- if(response.statusCode === 201){
- console.log("Document "+response.headers['location']+" created");
- b.submit();
- }
- else{
- console.log("POST caused "+response.statusCode+"!");
- b.submit();
- }
- });
-}
+ var request = client.request('POST', "/" + db, {
+ "Content-Type": "application/json",
+ "Connection": "keep-alive"
+ });
+ request.write(JSON.stringify(entity));
+ request.end();
+ request.once('response', function (response) {
+
+ if (response.statusCode === 201) {
+ console.log("Document " + response.headers['location'] + " created");
+ b.submit();
+ } else {
+ console.log("POST caused " + response.statusCode + "!");
+ b.submit();
+ }
+ });
+}
\ No newline at end of file
diff --git a/misc/geocouch-filler-js/lib/barrier.js b/misc/geocouch-filler-js/lib/barrier.js
deleted file mode 100644
index 59275ea..0000000
--- a/misc/geocouch-filler-js/lib/barrier.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
-* A simple barrier point coordination class for node.js
-*
-* See http://www.ioexception.de/2010/07/05/barrier-points-in-node-js/ for more details.
-*
-* @author Benjamin Erb | http://www.benjamin-erb.de
-*
-*/
-
-/**
-* @class
-*
-* Creates a new barrier for the given amount of parties.
-* @param parties
-* @param barrierCallback
-* @param abortCallback
-* @return
-*/
-var Barrier = exports.Barrier = function(parties, barrierCallback, abortCallback)
-{
-this.parties = parties;
-this.barrierCallback = barrierCallback;
-this.abortCallback = abortCallback;
-
-this.running = true;
-this.count = 0;
-};
-
-/**
-* Signals a completion of one of the parties.
-* @return
-*/
-Barrier.prototype.submit = function()
-{
-if (++this.count === this.parties && this.running)
-{
-this.barrierCallback();
-}
-};
-
-/**
-* Signals an abort by one of the parties. If not callback is passed, the default abort callback will be executed.
-* @param customAbortCallback Optional callback that should be executed due to the abort.
-* @return
-*/
-Barrier.prototype.abort = function(customAbortCallback)
-{
-if (this.running && customAbortCallback)
-{
-customAbortCallback();
-}
-else if (this.running && this.abortCallback)
-{
-this.abortCallback();
-}
-this.running = false;
-};
diff --git a/misc/geocouch-filler-js/node_modules/barrier.js b/misc/geocouch-filler-js/node_modules/barrier.js
new file mode 100644
index 0000000..705fce7
--- /dev/null
+++ b/misc/geocouch-filler-js/node_modules/barrier.js
@@ -0,0 +1,41 @@
+/**
+ * A simple barrier point coordination class for node.js
+ *
+ * See http://www.ioexception.de/2010/07/05/barrier-points-in-node-js/ for more details.
+ *
+ * @class Creates a new barrier for the given amount of parties.
+ * @param parties
+ * @param barrierCallback
+ * @param abortCallback
+ * @author Benjamin Erb | http://www.benjamin-erb.de
+ */
+var Barrier = exports.Barrier = function (parties, barrierCallback, abortCallback) {
+ this.parties = parties;
+ this.barrierCallback = barrierCallback;
+ this.abortCallback = abortCallback;
+
+ this.running = true;
+ this.count = 0;
+ };
+
+/**
+ * Signals a completion of one of the parties.
+ */
+Barrier.prototype.submit = function () {
+ if (++this.count === this.parties && this.running) {
+ this.barrierCallback();
+ }
+};
+
+/**
+ * Signals an abort by one of the parties. If not callback is passed, the default abort callback will be executed.
+ * @param customAbortCallback Optional callback that should be executed due to the abort.
+ */
+Barrier.prototype.abort = function (customAbortCallback) {
+ if (this.running && customAbortCallback) {
+ customAbortCallback();
+ } else if (this.running && this.abortCallback) {
+ this.abortCallback();
+ }
+ this.running = false;
+};
\ No newline at end of file