Skip to content

Commit

Permalink
Add -points command with x= and y= options
Browse files Browse the repository at this point in the history
  • Loading branch information
mbloch committed Nov 14, 2014
1 parent f8a87a7 commit 1d7af36
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 47 deletions.
64 changes: 61 additions & 3 deletions mapshaper.js
Original file line number Diff line number Diff line change
Expand Up @@ -11616,6 +11616,41 @@ api.mergeFiles = function(files, opts) {



api.createPointLayer = function(srcLyr, opts) {
var data = srcLyr.data,
nulls = 0,
destLyr;

if (!data) stop("[points] layer is missing a data table");
if (!opts.x || !opts.y || !data.fieldExists(opts.x) || !data.fieldExists(opts.y)) {
stop("[points] missing x,y data fields");
}

destLyr = {
info: srcLyr.info,
geometry_type: 'point',
data: opts.no_replace ? data.clone() : data
};
destLyr.shapes = data.getRecords().map(function(rec) {
var x = rec[opts.x],
y = rec[opts.y];
if (isNaN(x) || isNaN(y)) {
nulls++;
return null;
}
return [[x, y]];
});

if (nulls > 0) {
message(utils.format('[points] %d/%d points are null', nulls, data.size()));
}

return destLyr;
};




api.renameLayers = function(layers, names) {
if (!names || names.length > 0 === false) {
names = ['layer'];
Expand Down Expand Up @@ -12661,6 +12696,9 @@ api.runCommand = function(cmd, dataset, cb) {
} else if (name == 'o') {
api.exportFiles(Utils.defaults({layers: targetLayers}, dataset), opts);

} else if (name == 'points') {
newLayers = MapShaper.applyCommand(api.createPointLayer, targetLayers, opts);

} else if (name == 'rename-layers') {
api.renameLayers(targetLayers, opts.names);

Expand Down Expand Up @@ -13313,6 +13351,13 @@ function validateLinesOpts(cmd) {
}
}

function validatePointsOpts(cmd) {
if (!cmd.options.x || !cmd.options.y) {
error("command requires names of x and y fields");
}
}


function validateInnerLinesOpts(cmd) {
if (cmd._.length > 0) {
error("command takes no arguments");
Expand Down Expand Up @@ -13737,6 +13782,13 @@ MapShaper.getOptionParser = function() {
.option("convert-holes", {type: "flag"}) // testing
.option("target", targetOpt);

parser.command("innerlines")
.describe("convert polygons to polylines along shared boundaries")
.validate(validateInnerLinesOpts)
.option("name", nameOpt)
.option("no-replace", noReplaceOpt)
.option("target", targetOpt);

parser.command("lines")
.describe("convert polygons to classified polylines")
.validate(validateLinesOpts)
Expand All @@ -13749,9 +13801,15 @@ MapShaper.getOptionParser = function() {
.option("no-replace", noReplaceOpt)
.option("target", targetOpt);

parser.command("innerlines")
.describe("convert polygons to polylines along shared boundaries")
.validate(validateInnerLinesOpts)
parser.command("points")
.describe("create a point layer from data fields")
.validate(validatePointsOpts)
.option("x", {
describe: "field containing x coordinate"
})
.option("y", {
describe: "field containing y coordinate"
})
.option("name", nameOpt)
.option("no-replace", noReplaceOpt)
.option("target", targetOpt);
Expand Down
7 changes: 7 additions & 0 deletions src/cli/mapshaper-option-validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,13 @@ function validateLinesOpts(cmd) {
}
}

function validatePointsOpts(cmd) {
if (!cmd.options.x || !cmd.options.y) {
error("command requires names of x and y fields");
}
}


function validateInnerLinesOpts(cmd) {
if (cmd._.length > 0) {
error("command takes no arguments");
Expand Down
19 changes: 16 additions & 3 deletions src/cli/mapshaper-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,13 @@ MapShaper.getOptionParser = function() {
.option("convert-holes", {type: "flag"}) // testing
.option("target", targetOpt);

parser.command("innerlines")
.describe("convert polygons to polylines along shared boundaries")
.validate(validateInnerLinesOpts)
.option("name", nameOpt)
.option("no-replace", noReplaceOpt)
.option("target", targetOpt);

parser.command("lines")
.describe("convert polygons to classified polylines")
.validate(validateLinesOpts)
Expand All @@ -335,9 +342,15 @@ MapShaper.getOptionParser = function() {
.option("no-replace", noReplaceOpt)
.option("target", targetOpt);

parser.command("innerlines")
.describe("convert polygons to polylines along shared boundaries")
.validate(validateInnerLinesOpts)
parser.command("points")
.describe("create a point layer from data fields")
.validate(validatePointsOpts)
.option("x", {
describe: "field containing x coordinate"
})
.option("y", {
describe: "field containing y coordinate"
})
.option("name", nameOpt)
.option("no-replace", noReplaceOpt)
.option("target", targetOpt);
Expand Down
4 changes: 4 additions & 0 deletions src/cli/mapshaper-run-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mapshaper-innerlines
mapshaper-join
mapshaper-keep-shapes
mapshaper-merge-files
mapshaper-points
mapshaper-rename-layers
mapshaper-simplify
mapshaper-split
Expand Down Expand Up @@ -108,6 +109,9 @@ api.runCommand = function(cmd, dataset, cb) {
} else if (name == 'o') {
api.exportFiles(Utils.defaults({layers: targetLayers}, dataset), opts);

} else if (name == 'points') {
newLayers = MapShaper.applyCommand(api.createPointLayer, targetLayers, opts);

} else if (name == 'rename-layers') {
api.renameLayers(targetLayers, opts.names);

Expand Down
33 changes: 33 additions & 0 deletions src/commands/mapshaper-points.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* @requires mapshaper-data-table, mapshaper-dataset-utils */

api.createPointLayer = function(srcLyr, opts) {
var data = srcLyr.data,
nulls = 0,
destLyr;

if (!data) stop("[points] layer is missing a data table");
if (!opts.x || !opts.y || !data.fieldExists(opts.x) || !data.fieldExists(opts.y)) {
stop("[points] missing x,y data fields");
}

destLyr = {
info: srcLyr.info,
geometry_type: 'point',
data: opts.no_replace ? data.clone() : data
};
destLyr.shapes = data.getRecords().map(function(rec) {
var x = rec[opts.x],
y = rec[opts.y];
if (isNaN(x) || isNaN(y)) {
nulls++;
return null;
}
return [[x, y]];
});

if (nulls > 0) {
message(utils.format('[points] %d/%d points are null', nulls, data.size()));
}

return destLyr;
};
43 changes: 2 additions & 41 deletions www/mapshaper.js
Original file line number Diff line number Diff line change
Expand Up @@ -5833,37 +5833,6 @@ geom.getAvgPathXY = function(ids, arcs) {
};
};

geom.getPathCentroid = function(ids, arcs) {
var iter = arcs.getShapeIter(ids),
sum = 0,
sumX = 0,
sumY = 0,
ax, ay, tmp, area;
if (!iter.hasNext()) return null;
ax = iter.x;
ay = iter.y;
while (iter.hasNext()) {
tmp = ax * iter.y - ay * iter.x;
sum += tmp;
sumX += tmp * (iter.x + ax);
sumY += tmp * (iter.y + ay);
ax = iter.x;
ay = iter.y;
}
area = sum / 2;
if (area === 0) {
return geom.getAvgPathXY(ids, arcs);
} else return {
x: sumX / (6 * area),
y: sumY / (6 * area)
};
};

geom.getShapeCentroid = function(shp, arcs) {
var maxPath = geom.getMaxPath(shp, arcs);
return maxPath ? geom.getPathCentroid(maxPath, arcs) : null;
};

// Return true if point is inside or on boundary of a shape
//
geom.testPointInShape = function(x, y, shp, arcs) {
Expand All @@ -5881,14 +5850,6 @@ geom.testPointInShape = function(x, y, shp, arcs) {
return isOn || isIn;
};

// Get a point suitable for anchoring a label
// Method:
// - find centroid
// - ...
//
geom.getInteriorPoint = function(shp, arcs) {

};

geom.getPointToPathDistance = function(px, py, ids, arcs) {
var iter = arcs.getShapeIter(ids);
Expand Down Expand Up @@ -9704,7 +9665,7 @@ MapShaper.exportGeoJSONString = function(lyr, arcs, opts) {
useFeatures = useProperties || opts.id_field,
stringify = JSON.stringify;

if (opts.pretty) {
if (opts.prettify) {
stringify = MapShaper.getFormattedStringify(['bbox', 'coordinates']);
}
if (properties && properties.length !== lyr.shapes.length) {
Expand Down Expand Up @@ -10739,7 +10700,7 @@ MapShaper.exportTopoJSON = function(dataset, opts) {
stringify = JSON.stringify,
filename;

if (opts.pretty) {
if (opts.prettify) {
stringify = MapShaper.getFormattedStringify('coordinates,arcs,bbox,translate,scale'.split(','));
}
if (opts.output_file) {
Expand Down

0 comments on commit 1d7af36

Please sign in to comment.