Class: NSWTopo::GeoJSON::Collection
- Inherits:
-
Object
- Object
- NSWTopo::GeoJSON::Collection
- Extended by:
- Forwardable
- Includes:
- Enumerable
- Defined in:
- lib/nswtopo/gis/geojson/collection.rb
Instance Attribute Summary collapse
-
#features ⇒ Object
readonly
Returns the value of attribute features.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#projection ⇒ Object
readonly
Returns the value of attribute projection.
Class Method Summary collapse
Instance Method Summary collapse
- #<<(feature) ⇒ Object (also: #push)
- #bbox ⇒ Object
- #bbox_centre ⇒ Object
- #bbox_extents ⇒ Object
-
#bounds ⇒ Object
TODO: what about empty collections?.
- #buffer(*margins, **options) ⇒ Object
- #clip(polygon) ⇒ Object
- #dissolve_points ⇒ Object
- #each(&block) ⇒ Object
- #explode ⇒ Object
-
#initialize(projection: DEFAULT_PROJECTION, features: [], name: nil) ⇒ Collection
constructor
A new instance of Collection.
- #map!(&block) ⇒ Object
- #merge(other) ⇒ Object
- #merge!(other) ⇒ Object
- #minimum_bbox_angle(*margins) ⇒ Object
- #multi ⇒ Object
- #reject!(&block) ⇒ Object
- #reproject_to(projection) ⇒ Object
- #reproject_to_wgs84 ⇒ Object
- #rotate_by_degrees!(angle) ⇒ Object
- #to_h ⇒ Object
- #to_json(**extras) ⇒ Object
- #union ⇒ Object
- #with_features(features) ⇒ Object
- #with_name(name) ⇒ Object
- #with_sql(sql, name: @name) ⇒ Object
Constructor Details
#initialize(projection: DEFAULT_PROJECTION, features: [], name: nil) ⇒ Collection
Returns a new instance of Collection.
6 7 8 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 6 def initialize(projection: DEFAULT_PROJECTION, features: [], name: nil) @projection, @features, @name = projection, features, name end |
Instance Attribute Details
#features ⇒ Object (readonly)
Returns the value of attribute features.
9 10 11 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 9 def features @features end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
9 10 11 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 9 def name @name end |
#projection ⇒ Object (readonly)
Returns the value of attribute projection.
9 10 11 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 9 def projection @projection end |
Class Method Details
.load(json, projection: nil, name: nil) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 11 def self.load(json, projection: nil, name: nil) collection = JSON.parse(json) crs_name = collection.dig "crs", "properties", "name" projection ||= crs_name ? Projection.new(crs_name) : DEFAULT_PROJECTION name ||= collection["name"] collection["features"].select do |feature| feature["geometry"] end.map do |feature| geometry, properties = feature.values_at "geometry", "properties" type, coordinates = geometry.values_at "type", "coordinates" raise Error, "unsupported geometry type: #{type}" unless TYPES === type GeoJSON.const_get(type)[coordinates, properties] end.then do |features| new projection: projection, features: features, name: name end rescue JSON::ParserError raise Error, "invalid GeoJSON data" end |
Instance Method Details
#<<(feature) ⇒ Object Also known as: push
30 31 32 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 30 def <<(feature) tap { @features << feature } end |
#bbox ⇒ Object
146 147 148 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 146 def bbox GeoJSON.polygon [bounds.inject(&:product).values_at(0,2,3,1,0)], projection: @projection end |
#bbox_centre ⇒ Object
150 151 152 153 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 150 def bbox_centre midpoint = bounds.map { |min, max| (max + min) / 2 } GeoJSON.point midpoint, projection: @projection end |
#bbox_extents ⇒ Object
155 156 157 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 155 def bbox_extents bounds.map { |min, max| max - min } end |
#bounds ⇒ Object
TODO: what about empty collections?
142 143 144 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 142 def bounds map(&:bounds).transpose.map(&:flatten).map(&:minmax) end |
#buffer(*margins, **options) ⇒ Object
133 134 135 136 137 138 139 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 133 def buffer(*margins, **) map do |feature| feature.buffer(*margins, **) end.then do |features| with_features features end end |
#clip(polygon) ⇒ Object
125 126 127 128 129 130 131 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 125 def clip(polygon) OS.ogr2ogr "-f", "GeoJSON", "-lco", "RFC7946=NO", "-clipsrc", polygon.wkt, "/vsistdout/", "GeoJSON:/vsistdin/" do |stdin| stdin.puts to_json end.then do |json| Collection.load json, projection: @projection end end |
#dissolve_points ⇒ Object
112 113 114 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 112 def dissolve_points with_features map(&:dissolve_points) end |
#each(&block) ⇒ Object
36 37 38 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 36 def each(&block) block_given? ? tap { @features.each(&block) } : @features.each end |
#explode ⇒ Object
94 95 96 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 94 def explode with_features flat_map(&:explode) end |
#map!(&block) ⇒ Object
40 41 42 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 40 def map!(&block) tap { @features.map!(&block) } end |
#merge(other) ⇒ Object
102 103 104 105 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 102 def merge(other) raise Error, "can't merge different projections" unless @projection == other.projection with_features @features + other.features end |
#merge!(other) ⇒ Object
107 108 109 110 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 107 def merge!(other) raise Error, "can't merge different projections" unless @projection == other.projection tap { @features.concat other.features } end |
#minimum_bbox_angle(*margins) ⇒ Object
159 160 161 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 159 def minimum_bbox_angle(*margins) dissolve_points.union.first.minimum_bbox_angle(*margins) end |
#multi ⇒ Object
98 99 100 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 98 def multi with_features map(&:multi) end |
#reject!(&block) ⇒ Object
44 45 46 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 44 def reject!(&block) tap { @features.reject!(&block) } end |
#reproject_to(projection) ⇒ Object
48 49 50 51 52 53 54 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 48 def reproject_to(projection) return self if self.projection == projection json = OS.ogr2ogr "-t_srs", projection, "-f", "GeoJSON", "-lco", "RFC7946=NO", "/vsistdout/", "GeoJSON:/vsistdin/" do |stdin| stdin.puts to_json end Collection.load json, projection: projection end |
#reproject_to_wgs84 ⇒ Object
56 57 58 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 56 def reproject_to_wgs84 reproject_to Projection.wgs84 end |
#rotate_by_degrees!(angle) ⇒ Object
121 122 123 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 121 def rotate_by_degrees!(angle) map! { |feature| feature.rotate_by_degrees(angle) } end |
#to_h ⇒ Object
60 61 62 63 64 65 66 67 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 60 def to_h { "type" => "FeatureCollection", "name" => @name, "crs" => { "type" => "name", "properties" => { "name" => @projection } }, "features" => map(&:to_h) }.compact end |
#to_json(**extras) ⇒ Object
73 74 75 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 73 def to_json(**extras) to_h.merge(extras).to_json end |
#union ⇒ Object
116 117 118 119 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 116 def union return self if none? with_features [inject(&:+)] end |
#with_features(features) ⇒ Object
77 78 79 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 77 def with_features(features) Collection.new projection: @projection, name: @name, features: features end |
#with_name(name) ⇒ Object
81 82 83 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 81 def with_name(name) Collection.new projection: @projection, name: name, features: @features end |
#with_sql(sql, name: @name) ⇒ Object
85 86 87 88 89 90 91 92 |
# File 'lib/nswtopo/gis/geojson/collection.rb', line 85 def with_sql(sql, name: @name) json = OS.ogr2ogr *%w[-f GeoJSON -lco RFC7946=NO /vsistdout/ GeoJSON:/vsistdin/ -dialect SQLite -sql], sql do |stdin| stdin.puts to_json end Collection.load(json, projection: @projection).with_name(name) rescue OS::Error raise "GDAL with SQLite support required" end |