class NSWTopo::Shapefile::Layer
def counts
def counts raise NoLayerError, "no layer name provided" unless @layer count = ?_ * @fields.map(&:size).max + "count" where = %Q[WHERE (%s)] % [*@where].join(") AND (") if @where field_list = %Q["%s"] % @fields.join('", "') sql = <<~SQL % [field_list, count, @layer, where, field_list] SELECT %s, count(*) AS "%s" FROM "%s" %s GROUP BY %s SQL json = OS.ogr2ogr *%w[-f GeoJSON -lco RFC7946=NO -dialect sqlite -sql], sql, "/vsistdout/", @source.path JSON.parse(json)["features"].map do |feature| feature["properties"] end.map do |properties| [properties.slice(*@fields), properties[count]] end rescue OS::Error => error raise unless /no such column: (.*)$/ === error.message raise "invalid field: #{$1}" end
def features
def features raise "can't specify both SQL and where clause" if @sql && @where raise "can't specify both SQL and layer name" if @sql && @layer raise "no layer name or SQL specified" unless @layer || @sql sql = ["-sql", sql] if @sql where = ["-where", "(" << Array(@where).join(") AND (") << ")"] if @where srs = ["-t_srs", @projection] if @projection spat = ["-spat", *@geometry.bounds.transpose.flatten, "-spat_srs", @geometry.projection] if @geometry misc = %w[-mapFieldType Date=Integer,DateTime=Integer -dim XY] json = OS.ogr2ogr *(sql || where), *srs, *spat, *misc, *%w[-f GeoJSON -lco RFC7946=NO /vsistdout/], @source.path, *@layer GeoJSON::Collection.load json, **{projection: @projection}.compact rescue OS::Error => error raise unless /Couldn't fetch requested layer (.*)!/ === error.message raise "no such layer: #{$1}" end
def info
def info raise NoLayerError, "no layer name provided" unless @layer info = OS.ogrinfo *%w[-ro -so -noextent], @source.path, @layer geom_type = info.match(/^Geometry: (.*)$/)&.[](1)&.delete(?\s) count = info.match(/^Feature Count: (\d+)$/)&.[](1) fields = info.scan(/^(.*): (.*?) \(\d+\.\d+\)$/).to_h wkt = info.each_line.slice_after(/^Layer SRS WKT:/).drop(1).first&.slice_before(/^\S/)&.first&.join epsg = OS.gdalsrsinfo("-o", "epsg", wkt)[/\d+/] if wkt and !wkt["unknown"] { name: @layer, geometry: geom_type, EPSG: epsg, features: count, fields: (fields unless fields.empty?) }.compact rescue OS::Error => error raise unless /Couldn't fetch requested layer (.*)!/ === error.message raise "no such layer: #{$1}" end
def initialize(source, layer: nil, where: nil, fields: nil, sql: nil, geometry: nil, projection: nil)
def initialize(source, layer: nil, where: nil, fields: nil, sql: nil, geometry: nil, projection: nil) @source, @layer, @where, @fields, @sql, @geometry, @projection = source, layer, where, fields, sql, geometry, projection end