Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ function getFeatures(url, callback) {
geometry: {},
properties: {}
};
// console.log(record);
// TODO: Crashes here when a Shape file has been appended to and number of
// records do not match in .shp and .dbf.
feature.properties = attrs.values;

switch(record.shapeType) {
Expand All @@ -60,18 +61,28 @@ function getFeatures(url, callback) {
}
break;
case Shp.ShpType.SHAPE_POLYGON:
var coordinates = [],
j, len,
ring, featureRing;
feature.geometry.type = Shp.GeoJsonType[record.shapeType];
feature.geometry.coordinates = [];
var ringsLen = record.shape.rings.length;
for (var j = 0; j < ringsLen; j++) {
var ring = record.shape.rings[j];
for (j = 0, len = record.shape.rings.length; j < len; j++) {
ring = record.shape.rings[j];
if (ring.length < 1) continue;
var featureRing = feature.geometry.coordinates[j] = [];
var ringLen = ring.length;
for (var k = 0; k < ringLen; k++) {
featureRing.push([ring[k].x, ring[k].y]);
featureRing = ring.map(function(point) {
return [point.x, point.y];
});
if (coordinates.length > 0 && ring.isClockwise) {
feature.geometry.type = 'MultiPolygon';
feature.geometry.coordinates.push(coordinates);
coordinates = [];
}
coordinates.push(featureRing);
}
if (feature.geometry.coordinates.length === 0)
feature.geometry.coordinates = coordinates;
else
feature.geometry.coordinates.push(coordinates);
break;
default:
throw(new Error("Error converting SHP to geojson: Unsupported feature type"))
Expand Down
19 changes: 15 additions & 4 deletions lib/shp.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
var fs = require('fs');
var BinaryReader = require('./BinaryReader');

function isClockwise(points) {
return points.reduce(function (sum, c, i, points) {
var n = points[(i+1)%points.length];
return sum + (n.x-c.x)*(n.y+c.y);
}, 0) >= 0;
}

var ShpFile = function(path) {
this.header = {};
this._reader = new BinaryReader(path+".shp");
Expand Down Expand Up @@ -266,7 +273,7 @@ function ShpPolyline(reader, size) {

reader.bigEndian = false;

this.box = {
this.box = {
x: reader.readDouble(),
y: reader.readDouble(),
width: reader.readDouble(),
Expand All @@ -289,14 +296,18 @@ function ShpPolyline(reader, size) {

// convert points, and ringOffsets arrays to an array of rings:
var removed = 0;
var split;
var split, ring;
ringOffsets.shift();
while(ringOffsets.length) {
split = ringOffsets.shift();
this.rings.push(points.splice(0,split-removed));
ring = points.splice(0,split-removed);
ring.isClockwise = isClockwise(ring);
this.rings.push(ring);
removed = split;
}
this.rings.push(points);
ring = points;
ring.isClockwise = isClockwise(ring);
this.rings.push(ring);
}
}

Expand Down
9 changes: 5 additions & 4 deletions test/shp.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ describe('Shapefile Reader', function() {
it('Can correctly convert multiPolygon shapefile to GeoJSON', function(done){
var good_json = JSON.parse(fs.readFileSync(__dirname + '/data/multipolygon.json', "utf8"));
shpFile.readFile(__dirname + '/data/multipolygon', function(error, data){
expect(data.features[0].geometry.coordinates[0][0][0]).to.be.closeTo(good_json.features[0].geometry.coordinates[0][0][0], 0.00001);
expect(data.features[0].geometry.coordinates[0][0][1]).to.be.closeTo(good_json.features[0].geometry.coordinates[0][0][1], 0.00001);
expect(data.features[0].geometry.coordinates[0][1][0]).to.be.closeTo(good_json.features[0].geometry.coordinates[0][1][0], 0.00001);
expect(data.features[0].geometry.coordinates[0][1][1]).to.be.closeTo(good_json.features[0].geometry.coordinates[0][1][1], 0.00001);
expect(data.features[0].geometry.type).to.equal('MultiPolygon');
expect(data.features[0].geometry.coordinates[0][0][0][0]).to.be.closeTo(good_json.features[0].geometry.coordinates[0][0][0][0], 0.00001);
expect(data.features[0].geometry.coordinates[0][0][0][1]).to.be.closeTo(good_json.features[0].geometry.coordinates[0][0][0][1], 0.00001);
expect(data.features[0].geometry.coordinates[0][0][1][0]).to.be.closeTo(good_json.features[0].geometry.coordinates[0][0][1][0], 0.00001);
expect(data.features[0].geometry.coordinates[0][0][1][1]).to.be.closeTo(good_json.features[0].geometry.coordinates[0][0][1][1], 0.00001);
});
done();
});
Expand Down