Skip to content

Commit

Permalink
move georss, fix modules
Browse files Browse the repository at this point in the history
  • Loading branch information
nofxx committed Jan 29, 2011
1 parent a7f4c95 commit 64baa72
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 240 deletions.
10 changes: 5 additions & 5 deletions lib/geo_ruby.rb
@@ -1,5 +1,5 @@
$:.unshift(File.dirname(__FILE__)) unless
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
# $:.unshift(File.dirname(__FILE__)) #unless
# $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))

require 'geo_ruby/simple_features/helper'
require 'geo_ruby/simple_features/ewkt_parser'
Expand All @@ -15,9 +15,9 @@
require 'geo_ruby/simple_features/geometry_collection'
require 'geo_ruby/simple_features/envelope'
require 'geo_ruby/simple_features/geometry_factory'
require 'geo_ruby/simple_features/georss_parser'

# Include if you need
# Require if you need
# require 'geo_ruby/shp4r/shp'
# require 'geo_ruby/gpx4r/gpx'
# require 'geo_ruby/simple_features/geojson_parser'
# require 'geo_ruby/geojson'
# require 'geo_ruby/georss'
196 changes: 97 additions & 99 deletions lib/geo_ruby/geojson.rb
@@ -1,131 +1,129 @@
# GeoJSON parser based on the v1.0 spec at http://geojson.org/geojson-spec.html

module GeoRuby
module SimpleFeatures
#Raised when an error in the GeoJSON string is detected
class GeojsonFormatError < StandardError
end
#Raised when an error in the GeoJSON string is detected
class GeojsonFormatError < StandardError
end

# Class added to support geojson 'Feature' objects
class GeojsonFeature
attr_accessor :geometry, :properties, :id
# Class added to support geojson 'Feature' objects
class GeojsonFeature
attr_accessor :geometry, :properties, :id

def initialize(geometry, properties = {}, id = nil)
@geometry = geometry
@properties = properties
@id = id
end
def initialize(geometry, properties = {}, id = nil)
@geometry = geometry
@properties = properties
@id = id
end

def ==(other)
if (self.class != other.class)
false
else
(self.id == other.id) && (self.geometry == other.geometry) && (self.properties == other.properties)
end
def ==(other)
if (self.class != other.class)
false
else
(self.id == other.id) && (self.geometry == other.geometry) && (self.properties == other.properties)
end
end

def to_json(options={})
output = {}
output[:type] = 'Feature'
output[:geometry] = geometry
output[:properties] = properties
output[:id] = id unless id.nil?
output.to_json(options)
end
alias :as_geojson :to_json
def to_json(options={})
output = {}
output[:type] = 'Feature'
output[:geometry] = geometry
output[:properties] = properties
output[:id] = id unless id.nil?
output.to_json(options)
end
alias :as_geojson :to_json
end

# Class added to support geojson 'Feature Collection' objects
class GeojsonFeatureCollection
attr_accessor :features
# Class added to support geojson 'Feature Collection' objects
class GeojsonFeatureCollection
attr_accessor :features

def initialize(features)
@features = features
end
def initialize(features)
@features = features
end

def ==(other)
if (self.class != other.class) || (features.size != other.features.size)
return false
else
features.each_index do |index|
return false if self.features[index] != other.features[index]
end
def ==(other)
if (self.class != other.class) || (features.size != other.features.size)
return false
else
features.each_index do |index|
return false if self.features[index] != other.features[index]
end
true
end
true
end

def to_json(options = {})
{:type => 'FeatureCollection',
:features => features}.to_json(options)
end
alias :as_geojson :to_json
def to_json(options = {})
{:type => 'FeatureCollection',
:features => features}.to_json(options)
end
alias :as_geojson :to_json
end


class GeojsonParser
attr_reader :geometry
class GeojsonParser
attr_reader :geometry

def parse(geojson, srid=DEFAULT_SRID)
@geometry = nil
geohash = JSON.parse(geojson)
parse_geohash(geohash, srid)
end
def parse(geojson, srid=DEFAULT_SRID)
@geometry = nil
geohash = JSON.parse(geojson)
parse_geohash(geohash, srid)
end

private

def parse_geohash(geohash, srid)
srid = srid_from_crs(geohash['crs']) || srid
case geohash['type']
when 'Point', 'MultiPoint', 'LineString', 'MultiLineString', 'Polygon', 'MultiPolygon', 'GeometryCollection'
@geometry = parse_geometry(geohash, srid)
when 'Feature'
@geometry = parse_geojson_feature(geohash, srid)
when 'FeatureCollection'
@geometry = parse_geojson_feature_collection(geohash, srid)
else
GeojsonFormatError.new('Unknown GeoJSON type')
end
private

def parse_geohash(geohash, srid)
srid = srid_from_crs(geohash['crs']) || srid
case geohash['type']
when 'Point', 'MultiPoint', 'LineString', 'MultiLineString', 'Polygon', 'MultiPolygon', 'GeometryCollection'
@geometry = parse_geometry(geohash, srid)
when 'Feature'
@geometry = parse_geojson_feature(geohash, srid)
when 'FeatureCollection'
@geometry = parse_geojson_feature_collection(geohash, srid)
else
GeojsonFormatError.new('Unknown GeoJSON type')
end
end

def parse_geometry(geohash, srid)
srid = srid_from_crs(geohash['crs']) || srid
if geohash['type'] == 'GeometryCollection'
parse_geometry_collection(geohash, srid)
else
klass = GeoRuby::SimpleFeatures.const_get(geohash['type'])
klass.from_coordinates(geohash['coordinates'], srid, false, false)
end
def parse_geometry(geohash, srid)
srid = srid_from_crs(geohash['crs']) || srid
if geohash['type'] == 'GeometryCollection'
parse_geometry_collection(geohash, srid)
else
klass = GeoRuby::SimpleFeatures.const_get(geohash['type'])
klass.from_coordinates(geohash['coordinates'], srid, false, false)
end
end

def parse_geometry_collection(geohash, srid)
srid = srid_from_crs(geohash['crs']) || srid
geometries = geohash['geometries'].map{|g| parse_geometry(g,srid)}
GeometryCollection.from_geometries(geometries,srid)
end
def parse_geometry_collection(geohash, srid)
srid = srid_from_crs(geohash['crs']) || srid
geometries = geohash['geometries'].map{|g| parse_geometry(g,srid)}
GeometryCollection.from_geometries(geometries,srid)
end

def parse_geojson_feature(geohash, srid)
srid = srid_from_crs(geohash['crs']) || srid
geometry = parse_geometry(geohash['geometry'],srid)
GeojsonFeature.new(geometry, geohash['properties'], geohash['id'])
end
def parse_geojson_feature(geohash, srid)
srid = srid_from_crs(geohash['crs']) || srid
geometry = parse_geometry(geohash['geometry'],srid)
GeojsonFeature.new(geometry, geohash['properties'], geohash['id'])
end

def parse_geojson_feature_collection(geohash, srid)
srid = srid_from_crs(geohash['crs']) || srid
features = []
geohash['features'].each do |feature|
features << parse_geojson_feature(feature, srid)
end
GeojsonFeatureCollection.new(features)
def parse_geojson_feature_collection(geohash, srid)
srid = srid_from_crs(geohash['crs']) || srid
features = []
geohash['features'].each do |feature|
features << parse_geojson_feature(feature, srid)
end
GeojsonFeatureCollection.new(features)
end

def srid_from_crs(crs)
# We somehow need to map crs to srid, currently only support for EPSG
if crs && crs['type'] == 'OGC'
urn = crs['properties']['urn'].split(':')
return urn.last if urn[4] == 'EPSG'
end
return nil
def srid_from_crs(crs)
# We somehow need to map crs to srid, currently only support for EPSG
if crs && crs['type'] == 'OGC'
urn = crs['properties']['urn'].split(':')
return urn.last if urn[4] == 'EPSG'
end
return nil
end
end
end
133 changes: 133 additions & 0 deletions lib/geo_ruby/georss.rb
@@ -0,0 +1,133 @@
# require 'geo_ruby/simple_features/point'
# require 'geo_ruby/simple_features/line_string'
# require 'geo_ruby/simple_features/linear_ring'
# require 'geo_ruby/simple_features/polygon'
# require 'geo_ruby/simple_features/multi_point'
# require 'geo_ruby/simple_features/multi_line_string'
# require 'geo_ruby/simple_features/multi_polygon'
# require 'geo_ruby/simple_features/geometry_collection'
# require 'geo_ruby/simple_features/envelope'

module GeoRuby

#Raised when an error in the GeoRSS string is detected
class GeorssFormatError < StandardError
end

#Contains tags possibly found on GeoRss Simple geometries
class GeorssTags < Struct.new(:featuretypetag,:relationshiptag,:elev,:floor,:radius)
end

#Parses GeoRSS strings
#You can also use directly the static method Geometry.from_georss
class GeorssParser
attr_reader :georss_tags, :geometry

#Parses the georss geometry passed as argument and notifies the factory of events
#The parser assumes
def parse(georss,with_tags = false)
@geometry = nil
@georss_tags = GeorssTags.new
parse_geometry(georss,with_tags)
end

private
def parse_geometry(georss,with_tags)
georss.strip!
#check for W3CGeo first
if georss =~ /<[^:>]*:lat\s*>([^<]*)</
#if valid, it is W3CGeo
lat = $1.to_f
if georss =~ /<[^:>]*:long\s*>([^<]*)</
lon = $1.to_f
@geometry = Point.from_x_y(lon,lat)
else
raise GeorssFormatError.new("Bad W3CGeo GeoRSS format")
end
elsif georss =~ /^<\s*[^:>]*:where\s*>/
#GML format found
gml = $'.strip
if gml =~ /^<\s*[^:>]*:Point\s*>/
#gml point
if gml =~ /<\s*[^:>]*:pos\s*>([^<]*)/
point = $1.split(" ")
#lat comes first
@geometry = Point.from_x_y(point[1].to_f,point[0].to_f)
else
raise GeorssFormatError.new("Bad GML GeoRSS format: Malformed Point")
end
elsif gml =~ /^<\s*[^:>]*:LineString\s*>/
if gml =~ /<\s*[^:>]*:posList\s*>([^<]*)/
xy = $1.split(" ")
@geometry = LineString.new
0.upto(xy.size/2 - 1) { |index| @geometry << Point.from_x_y(xy[index*2 + 1].to_f,xy[index*2].to_f)}
else
raise GeorssFormatError.new("Bad GML GeoRSS format: Malformed LineString")
end
elsif gml =~ /^<\s*[^:>]*:Polygon\s*>/
if gml =~ /<\s*[^:>]*:posList\s*>([^<]*)/
xy = $1.split(" ")
@geometry = Polygon.new
linear_ring = LinearRing.new
@geometry << linear_ring
xy = $1.split(" ")
0.upto(xy.size/2 - 1) { |index| linear_ring << Point.from_x_y(xy[index*2 + 1].to_f,xy[index*2].to_f)}
else
raise GeorssFormatError.new("Bad GML GeoRSS format: Malformed Polygon")
end
elsif gml =~ /^<\s*[^:>]*:Envelope\s*>/
if gml =~ /<\s*[^:>]*:lowerCorner\s*>([^<]*)</
lc = $1.split(" ").collect { |x| x.to_f}.reverse
if gml =~ /<\s*[^:>]*:upperCorner\s*>([^<]*)</
uc = $1.split(" ").collect { |x| x.to_f}.reverse
@geometry = Envelope.from_coordinates([lc,uc])
else
raise GeorssFormatError.new("Bad GML GeoRSS format: Malformed Envelope")
end
else
raise GeorssFormatError.new("Bad GML GeoRSS format: Malformed Envelope")
end
else
raise GeorssFormatError.new("Bad GML GeoRSS format: Unknown geometry type")
end
else
#must be simple format
if georss =~ /^<\s*[^>:]*:point([^>]*)>(.*)</m
tags = $1
point = $2.gsub(","," ").split(" ")
@geometry = Point.from_x_y(point[1].to_f,point[0].to_f)
elsif georss =~ /^<\s*[^>:]*:line([^>]*)>(.*)</m
tags = $1
@geometry = LineString.new
xy = $2.gsub(","," ").split(" ")
0.upto(xy.size/2 - 1) { |index| @geometry << Point.from_x_y(xy[index*2 + 1].to_f,xy[index*2].to_f)}
elsif georss =~ /^<\s*[^>:]*:polygon([^>]*)>(.*)</m
tags = $1
@geometry = Polygon.new
linear_ring = LinearRing.new
@geometry << linear_ring
xy = $2.gsub(","," ").split(" ")
0.upto(xy.size/2 - 1) { |index| linear_ring << Point.from_x_y(xy[index*2 + 1].to_f,xy[index*2].to_f)}
elsif georss =~ /^<\s*[^>:]*:box([^>]*)>(.*)</m
tags = $1
corners = []
xy = $2.gsub(","," ").split(" ")
0.upto(xy.size/2 - 1) {|index| corners << Point.from_x_y(xy[index*2 + 1].to_f,xy[index*2].to_f)}
@geometry = Envelope.from_points(corners)
else
raise GeorssFormatError.new("Bad Simple GeoRSS format: Unknown geometry type")
end

#geometry found: parse tags
return unless with_tags

@georss_tags.featuretypetag = $1 if tags =~ /featuretypetag=['"]([^"']*)['"]/
@georss_tags.relationshiptag = $1 if tags =~ /relationshiptag=['"]([^'"]*)['"]/
@georss_tags.elev = $1.to_f if tags =~ /elev=['"]([^'"]*)['"]/
@georss_tags.floor = $1.to_i if tags =~ /floor=['"]([^'"]*)['"]/
@georss_tags.radius = $1.to_f if tags =~ /radius=['"]([^'"]*)['"]/

end
end
end
end

0 comments on commit 64baa72

Please sign in to comment.