Class: NSWTopo::GeoJSON::Collection

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable
Defined in:
lib/nswtopo/gis/geojson/collection.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

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

#featuresObject (readonly)

Returns the value of attribute features.



9
10
11
# File 'lib/nswtopo/gis/geojson/collection.rb', line 9

def features
  @features
end

#nameObject (readonly)

Returns the value of attribute name.



9
10
11
# File 'lib/nswtopo/gis/geojson/collection.rb', line 9

def name
  @name
end

#projectionObject (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).new 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

#bboxObject



113
114
115
# File 'lib/nswtopo/gis/geojson/collection.rb', line 113

def bbox
  GeoJSON.polygon [bounds.inject(&:product).values_at(0,2,3,1,0)], projection: @projection
end

#boundsObject

TODO: what about empty collections?



109
110
111
# File 'lib/nswtopo/gis/geojson/collection.rb', line 109

def bounds
  map(&:bounds).transpose.map(&:flatten).map(&:minmax)
end

#buffer(*margins, **options) ⇒ Object



96
97
98
99
100
101
102
# File 'lib/nswtopo/gis/geojson/collection.rb', line 96

def buffer(*margins, **options)
  map do |feature|
    feature.buffer(*margins, **options)
  end.then do |features|
    Collection.new projection: @projection, name: @name, features: features
  end
end

#clip(polygon) ⇒ Object



88
89
90
91
92
93
94
# File 'lib/nswtopo/gis/geojson/collection.rb', line 88

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

#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

#explodeObject



70
71
72
# File 'lib/nswtopo/gis/geojson/collection.rb', line 70

def explode
  Collection.new projection: @projection, name: @name, features: flat_map(&:explode)
end

#merge(other) ⇒ Object

Raises:



78
79
80
81
# File 'lib/nswtopo/gis/geojson/collection.rb', line 78

def merge(other)
  raise Error, "can't merge different projections" unless @projection == other.projection
  Collection.new projection: @projection, name: @name, features: @features + other.features
end

#merge!(other) ⇒ Object

Raises:



83
84
85
86
# File 'lib/nswtopo/gis/geojson/collection.rb', line 83

def merge!(other)
  raise Error, "can't merge different projections" unless @projection == other.projection
  tap { @features.concat other.features }
end

#multiObject



74
75
76
# File 'lib/nswtopo/gis/geojson/collection.rb', line 74

def multi
  Collection.new projection: @projection, name: @name, features: map(&:multi)
end

#rename(name = nil) ⇒ Object



104
105
106
# File 'lib/nswtopo/gis/geojson/collection.rb', line 104

def rename(name = nil)
  tap { @name = name }
end

#reproject_to(projection) ⇒ Object



40
41
42
43
44
45
46
# File 'lib/nswtopo/gis/geojson/collection.rb', line 40

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_wgs84Object



48
49
50
# File 'lib/nswtopo/gis/geojson/collection.rb', line 48

def reproject_to_wgs84
  reproject_to Projection.wgs84
end

#to_hObject



52
53
54
55
56
57
58
59
60
# File 'lib/nswtopo/gis/geojson/collection.rb', line 52

def to_h
  {
    "type" => "FeatureCollection",
    "crs" => { "type" => "name", "properties" => { "name" => @projection } },
    "features" => map(&:to_h)
  }.tap do |hash|
    hash["name"] = @name if @name
  end
end

#to_json(**extras) ⇒ Object



66
67
68
# File 'lib/nswtopo/gis/geojson/collection.rb', line 66

def to_json(**extras)
  to_h.merge(extras).to_json
end