6
6
layerHasGeometry ,
7
7
setOutputLayerName ,
8
8
initDataTable ,
9
- layerIsRectangle
9
+ layerIsRectangle ,
10
+ getFeatureCount
10
11
} from '../dataset/mapshaper-layer-utils' ;
11
12
import { mergeDatasetsIntoDataset } from '../dataset/mapshaper-merging' ;
12
13
import { importGeoJSON } from '../geojson/geojson-import' ;
@@ -17,21 +18,24 @@ import { probablyDecimalDegreeBounds, clampToWorldBounds } from '../geom/mapshap
17
18
import { Bounds } from '../geom/mapshaper-bounds' ;
18
19
import { densifyPathByInterval } from '../crs/mapshaper-densify' ;
19
20
import { bboxToCoords } from '../paths/mapshaper-rectangle-utils' ;
21
+ import { compileFeatureExpression } from '../expressions/mapshaper-feature-expressions' ;
20
22
21
23
// Create rectangles around each feature in a layer
22
24
cmd . rectangles = function ( targetLyr , targetDataset , opts ) {
23
- if ( ! layerHasGeometry ( targetLyr ) ) {
24
- stop ( "Layer is missing geometric shapes" ) ;
25
- }
26
25
var crsInfo = getDatasetCrsInfo ( targetDataset ) ;
27
26
var records = targetLyr . data ? targetLyr . data . getRecords ( ) : null ;
28
- var geometries = targetLyr . shapes . map ( function ( shp ) {
29
- var bounds = targetLyr . geometry_type == 'point' ?
30
- getPointFeatureBounds ( shp ) : targetDataset . arcs . getMultiShapeBounds ( shp ) ;
31
- bounds = applyRectangleOptions ( bounds , crsInfo . crs , opts ) ;
32
- if ( ! bounds ) return null ;
33
- return bboxToPolygon ( bounds . toArray ( ) , opts ) ;
34
- } ) ;
27
+ var geometries ;
28
+
29
+ if ( opts . bbox ) {
30
+ geometries = bboxExpressionToGeometries ( opts . bbox , targetLyr , targetDataset , opts ) ;
31
+
32
+ } else {
33
+ if ( ! layerHasGeometry ( targetLyr ) ) {
34
+ stop ( "Layer is missing geometric shapes" ) ;
35
+ }
36
+ geometries = shapesToBoxGeometries ( targetLyr , targetDataset , opts ) ;
37
+ }
38
+
35
39
var geojson = {
36
40
type : 'FeatureCollection' ,
37
41
features : geometries . map ( function ( geom , i ) {
@@ -53,6 +57,39 @@ cmd.rectangles = function(targetLyr, targetDataset, opts) {
53
57
return outputLayers ;
54
58
} ;
55
59
60
+ function shapesToBoxGeometries ( lyr , dataset , opts ) {
61
+ var crsInfo = getDatasetCrsInfo ( dataset ) ;
62
+ return lyr . shapes . map ( function ( shp ) {
63
+ var bounds = lyr . geometry_type == 'point' ?
64
+ getPointFeatureBounds ( shp ) : dataset . arcs . getMultiShapeBounds ( shp ) ;
65
+ bounds = applyRectangleOptions ( bounds , crsInfo . crs , opts ) ;
66
+ if ( ! bounds ) return null ;
67
+ return bboxToPolygon ( bounds . toArray ( ) , opts ) ;
68
+ } ) ;
69
+ }
70
+
71
+ function bboxExpressionToGeometries ( exp , lyr , dataset , opts ) {
72
+ var compiled = compileFeatureExpression ( exp , lyr , dataset . arcs , { } ) ;
73
+ var n = getFeatureCount ( lyr ) ;
74
+ var result ;
75
+ var geometries = [ ] ;
76
+ for ( var i = 0 ; i < n ; i ++ ) {
77
+ result = compiled ( i ) ;
78
+ if ( ! looksLikeBbox ( result ) ) {
79
+ stop ( 'Invalid bbox value (expected a GeoJSON-type bbox):' , result ) ;
80
+ }
81
+ geometries . push ( bboxToPolygon ( result ) ) ;
82
+ }
83
+ return geometries ;
84
+ }
85
+
86
+ function looksLikeBbox ( o ) {
87
+ if ( ! o || o . length != 4 ) return false ;
88
+ if ( o . some ( isNaN ) ) return false ;
89
+ if ( o [ 0 ] <= o [ 2 ] == false || o [ 1 ] <= o [ 3 ] == false ) return false ;
90
+ return true ;
91
+ }
92
+
56
93
// Create rectangles around one or more target layers
57
94
//
58
95
cmd . rectangle2 = function ( target , opts ) {
0 commit comments