diff --git a/mapshaper.js b/mapshaper.js index d7c450e7..0aec2c0e 100644 --- a/mapshaper.js +++ b/mapshaper.js @@ -25429,8 +25429,11 @@ ${svg} .option('no-replace', noReplaceOpt); parser.command('rectangles') - .describe('create a rectangle around each feature in a layer') + .describe('create a rectangle for each feature in a layer') .option('offset', offsetOpt) + .option('bbox', { + describe: 'Use an expression to generate a rectangle for each feature' + }) .option('aspect-ratio', aspectRatioOpt) .option('name', nameOpt) .option('target', targetOpt) @@ -38806,18 +38809,20 @@ ${svg} // Create rectangles around each feature in a layer cmd.rectangles = function(targetLyr, targetDataset, opts) { - if (!layerHasGeometry(targetLyr)) { - stop("Layer is missing geometric shapes"); - } var crsInfo = getDatasetCrsInfo(targetDataset); var records = targetLyr.data ? targetLyr.data.getRecords() : null; - var geometries = targetLyr.shapes.map(function(shp) { - var bounds = targetLyr.geometry_type == 'point' ? - getPointFeatureBounds(shp) : targetDataset.arcs.getMultiShapeBounds(shp); - bounds = applyRectangleOptions(bounds, crsInfo.crs, opts); - if (!bounds) return null; - return bboxToPolygon(bounds.toArray(), opts); - }); + var geometries; + + if (opts.bbox) { + geometries = bboxExpressionToGeometries(opts.bbox, targetLyr, targetDataset); + + } else { + if (!layerHasGeometry(targetLyr)) { + stop("Layer is missing geometric shapes"); + } + geometries = shapesToBoxGeometries(targetLyr, targetDataset, opts); + } + var geojson = { type: 'FeatureCollection', features: geometries.map(function(geom, i) { @@ -38839,6 +38844,39 @@ ${svg} return outputLayers; }; + function shapesToBoxGeometries(lyr, dataset, opts) { + var crsInfo = getDatasetCrsInfo(dataset); + return lyr.shapes.map(function(shp) { + var bounds = lyr.geometry_type == 'point' ? + getPointFeatureBounds(shp) : dataset.arcs.getMultiShapeBounds(shp); + bounds = applyRectangleOptions(bounds, crsInfo.crs, opts); + if (!bounds) return null; + return bboxToPolygon(bounds.toArray(), opts); + }); + } + + function bboxExpressionToGeometries(exp, lyr, dataset, opts) { + var compiled = compileFeatureExpression(exp, lyr, dataset.arcs, {}); + var n = getFeatureCount(lyr); + var result; + var geometries = []; + for (var i=0; i