class MapPLZ
MapPLZ
datastore
Constants
- DATABASES
Public Class Methods
flip_path(path)
click to toggle source
# File lib/mapplz.rb, line 335 def self.flip_path(path) path.map! do |pt| [pt[1].to_f, pt[0].to_f] end end
new(db = {})
click to toggle source
# File lib/mapplz.rb, line 14 def initialize(db = {}) @db_type = 'array' @db_client = db @db = { client: @db_client, type: @db_type } @my_array = [] @parser = SqlParser.new choose_db(ActiveRecord::Base.connection.adapter_name) if defined?(ActiveRecord) end
parse_wkt(geo_item, geom_string)
click to toggle source
# File lib/mapplz.rb, line 341 def self.parse_wkt(geo_item, geom_string) if geom_string.index('POINT') coordinates = geom_string.gsub('POINT', '').gsub('(', '').gsub(')', '').split(' ') geo_item[:lat] = coordinates[1].to_f geo_item[:lng] = coordinates[0].to_f elsif geom_string.index('LINESTRING') line_nodes = geom_string.gsub('LINESTRING', '').gsub('(', '').gsub(')', '').split(',') geo_item[:path] = line_nodes.map do |pt| pt = pt.split(' ') [pt[1].to_f, pt[0].to_f] end elsif geom_string.index('POLYGON') line_nodes = geom_string.gsub('POLYGON', '').gsub('(', '').gsub(')', '').split(', ') geo_item[:path] = line_nodes.map do |pt| pt = pt.split(' ') [pt[1].to_f, pt[0].to_f] end end geo_item end
standardize_geo(user_geo, lonlat = false, db = nil)
click to toggle source
# File lib/mapplz.rb, line 362 def self.standardize_geo(user_geo, lonlat = false, db = nil) return [user_geo] if user_geo.is_a?(GeoItem) geo_objects = [] if user_geo.is_a?(File) file_type = File.extname(user_geo) if ['.csv', '.tsv', '.tdv', '.txt', '.geojson', '.json'].include?(file_type) # parse this as if it were sent as a string user_geo = user_geo.read else # convert this with ogr2ogr and parse as a string begin `ogr2ogr -f "GeoJSON" tmp.geojson #{File.path(user_geo)} -t_srs EPSG:4326` user_geo = File.open('tmp.geojson').read rescue raise 'gdal was not installed, or format was not accepted by ogr2ogr' end end end if user_geo.is_a?(String) begin user_geo = JSON.parse(user_geo) rescue # not JSON - attempt CSV begin CSV.parse(user_geo.gsub('\"', '""'), headers: true) do |row| geo_objects += standardize_geo(row, lonlat, db) end return geo_objects rescue # not JSON or CSV - attempt mapplz parse raise MapPLZException, 'call code() to parse mapplz language' end end end if user_geo.is_a?(Array) && user_geo.length > 0 if user_geo[0].is_a?(Array) && user_geo[0].length > 0 if user_geo[0][0].is_a?(Array) || (user_geo[0][0].is_a?(Hash) && user_geo[0][0].key?(:lat) && user_geo[0][0].key?(:lng)) # lines and shapes user_geo.map! do |path| path_pts = [] path.each do |path_pt| if lonlat lat = path_pt[1] || path_pt[:lat] lng = path_pt[0] || path_pt[:lng] else lat = path_pt[0] || path_pt[:lat] lng = path_pt[1] || path_pt[:lng] end path_pts << [lat, lng] end # polygon border repeats first point if path_pts[0] == path_pts.last geo_type = 'polygon' path_pts = [path_pts] else geo_type = 'polyline' end geoitem = GeoItem.new(db) geoitem[:path] = path_pts geoitem[:type] = geo_type geoitem end return user_geo end end # multiple objects being added? iterate through if user_geo[0].is_a?(Hash) || user_geo[0].is_a?(Array) user_geo.each do |geo_piece| geo_objects += standardize_geo(geo_piece, lonlat, db) end return geo_objects end # first two spots are a coordinate validate_lat = user_geo[0].to_f != 0 || user_geo[0].to_s == '0' validate_lng = user_geo[1].to_f != 0 || user_geo[1].to_s == '0' if validate_lat && validate_lng geo_object = GeoItem.new(db) geo_object[:type] = 'point' if lonlat geo_object[:lat] = user_geo[1].to_f geo_object[:lng] = user_geo[0].to_f else geo_object[:lat] = user_geo[0].to_f geo_object[:lng] = user_geo[1].to_f end else fail 'no latitude or longitude found' end # assume user properties are an ordered array of values known to the user user_properties = user_geo.drop(2) # only one property and it's a string? check for JSON hash if user_properties.length == 1 && user_properties[0].is_a?(String) begin user_properties[0] = JSON.parse(user_properties[0]) rescue end end # only one property and it's a hash? it's a hash of properties if user_properties.length == 1 && user_properties[0].is_a?(Hash) user_properties[0].keys.each do |key| geo_object[key.to_sym] = user_properties[0][key] end else geo_object[:properties] = user_properties end geo_objects << geo_object elsif user_geo.is_a?(Hash) || user_geo.is_a?(CSV::Row) if user_geo.is_a?(CSV::Row) # convert CSV::Row to geo hash geo_hash = {} user_geo.headers.each do |header| geo_hash[header] = user_geo[header] end user_geo = geo_hash end # check for lat and lng validate_lat = false validate_lat = 'lat' if user_geo.key?('lat') || user_geo.key?(:lat) validate_lat ||= 'latitude' if user_geo.key?('latitude') || user_geo.key?(:latitude) validate_lng = false validate_lng = 'lng' if user_geo.key?('lng') || user_geo.key?(:lng) validate_lng ||= 'lon' if user_geo.key?('lon') || user_geo.key?(:lon) validate_lng ||= 'long' if user_geo.key?('long') || user_geo.key?(:long) validate_lng ||= 'longitude' if user_geo.key?('longitude') || user_geo.key?(:longitude) if validate_lat && validate_lng # single hash geo_object = GeoItem.new(db) geo_object[:lat] = user_geo[validate_lat].to_f geo_object[:lng] = user_geo[validate_lng].to_f geo_object[:type] = 'point' user_geo.keys.each do |key| next if key == validate_lat || key == validate_lng geo_object[key.to_sym] = user_geo[key] end geo_objects << geo_object elsif user_geo.key?('path') || user_geo.key?(:path) # try line or polygon path_pts = [] path = user_geo['path'] if user_geo.key?('path') path = user_geo[:path] if user_geo.key?(:path) if path_pts[0].is_a?(Array) && path_pts[0][0].is_a?(Array) # ring polygon path.each do |ring| ring.map! do |path_pt| if lonlat lat = path_pt[1] || path_pt[:lat] lng = path_pt[0] || path_pt[:lng] else lat = path_pt[0] || path_pt[:lat] lng = path_pt[1] || path_pt[:lng] end [lat, lng] end end path_pts = path else path.each do |path_pt| if lonlat lat = path_pt[1] || path_pt[:lat] lng = path_pt[0] || path_pt[:lng] else lat = path_pt[0] || path_pt[:lat] lng = path_pt[1] || path_pt[:lng] end path_pts << [lat, lng] end # polygon border repeats first point if path_pts[0] == path_pts.last geo_type = 'polygon' path_pts = [path_pts] else geo_type = 'polyline' end end geoitem = GeoItem.new(db) geoitem[:path] = path_pts geoitem[:type] = geo_type property_list = user_geo.clone property_list = property_list[:properties] if property_list.key?(:properties) property_list = property_list['properties'] if property_list.key?('properties') property_list.delete(:path) property_list.keys.each do |prop| geoitem[prop.to_sym] = property_list[prop] end geo_objects << geoitem elsif user_geo.key?('geo') || user_geo.key?(:geo) # this key is GeoJSON or WKT geotext = (user_geo['geo'] || user_geo[:geo]) if geotext.upcase.index('POINT(') || geotext.upcase.index('LINESTRING(') || geotext.upcase.index('POLYGON(') # try WKT geoitem = GeoItem.new(db) geoitem = MapPLZ.parse_wkt(geoitem, geotext) else # GeoJSON begin geoitem = standardize_geo(JSON.parse(geotext), lonlat, db)[0] rescue # did not recognize format raise 'did not recognize format in CSV geo column' end end user_geo.keys.each do |key| next if ['lat', 'lng', 'geo', 'geom', 'geojson', 'wkt', :lat, :lng, :geo, :geom, :geojson, :wkt].include?(key) geoitem[key.to_sym] = user_geo[key] end geo_objects << geoitem else # try GeoJSON if user_geo.key?(:type) user_geo['type'] = user_geo[:type] || '' user_geo['features'] = user_geo[:features] if user_geo.key?(:features) user_geo['properties'] = user_geo[:properties] || {} if user_geo.key?(:geometry) user_geo['geometry'] = user_geo[:geometry] user_geo['geometry']['type'] = user_geo[:geometry][:type] user_geo['geometry']['coordinates'] = user_geo[:geometry][:coordinates] end end if user_geo.key?('type') if user_geo['type'] == 'FeatureCollection' && user_geo.key?('features') # recursive onto features user_geo['features'].each do |feature| geo_objects += standardize_geo(feature, lonlat, db) end elsif user_geo.key?('geometry') && user_geo['geometry'].key?('coordinates') # each feature coordinates = user_geo['geometry']['coordinates'] if user_geo['geometry']['type'] == 'Point' geo_object = GeoItem.new(db) geo_object[:lat] = coordinates[1].to_f geo_object[:lng] = coordinates[0].to_f geo_object[:type] = 'point' geo_objects << geo_object elsif user_geo['geometry']['type'] == 'LineString' geo_object = GeoItem.new(db) MapPLZ.flip_path(coordinates) geo_object[:path] = coordinates geo_object[:type] = 'polyline' geo_objects << geo_object elsif user_geo['geometry']['type'] == 'Polygon' geo_object = GeoItem.new(db) coordinates.map! do |ring| MapPLZ.flip_path(ring) end geo_object[:path] = coordinates geo_object[:type] = 'polygon' geo_objects << geo_object elsif user_geo['geometry']['type'] == 'MultiPoint' coordinates.each do |point| geo_object = GeoItem.new(db) geo_object[:lat] = point[1].to_f geo_object[:lng] = point[0].to_f geo_object[:type] = 'point' geo_objects << geo_object end elsif user_geo['geometry']['type'] == 'MultiLineString' coordinates.each do |line| geo_object = GeoItem.new(db) geo_object[:path] = MapPLZ.flip_path(line) geo_object[:type] = 'polyline' geo_objects << geo_object end elsif user_geo['geometry']['type'] == 'MultiPolygon' coordinates.each do |poly| geo_object = GeoItem.new(db) poly.map! do |ring| MapPLZ.flip_path(ring) end geo_object[:path] = poly geo_object[:type] = 'polygon' geo_objects << geo_object end end # store properties on all generated geometries prop_keys = {} if user_geo.key?('properties') user_geo['properties'].keys.each do |key| prop_keys[key.to_sym] = user_geo['properties'][key] end end geo_objects.each do |geo| prop_keys.keys.each do |key| geo[key] = prop_keys[key] end end end end end end geo_objects end
Public Instance Methods
<<(user_geo)
click to toggle source
aliases for add
# File lib/mapplz.rb, line 683 def <<(user_geo) add(user_geo) end
add(user_geo, lonlat = false)
click to toggle source
# File lib/mapplz.rb, line 38 def add(user_geo, lonlat = false) begin geo_objects = MapPLZ.standardize_geo(user_geo, lonlat, @db) rescue MapPLZException geo_objects = code(user_geo) end if @db_type == 'array' @my_array += geo_objects elsif @db_type == 'mongodb' geo_objects.each do |geo_object| save_obj = geo_object.clone save_obj.delete(:_id) save_obj.delete(:lat) save_obj.delete(:lng) save_obj.delete(:path) save_obj.delete(:centroid) save_obj.delete(:type) save_obj[:geo] = JSON.parse(geo_object.to_geojson)['geometry'] reply = @db_client.insert(save_obj) geo_object[:_id] = reply.to_s end elsif @db_type == 'postgis' || @db_type == 'spatialite' geo_objects.each do |geo_object| geom = geo_object.to_wkt if @db_type == 'postgis' geojson_props = (JSON.parse(geo_object.to_geojson)['properties'] || {}) reply = @db_client.exec("INSERT INTO mapplz (properties, geom) VALUES ('#{geojson_props.to_json}', ST_GeomFromText('#{geom}')) RETURNING id") elsif @db_type == 'spatialite' reply = @db_client.execute("INSERT INTO mapplz (label, geom) VALUES ('#{geo_object[:label] || ''}', AsText('#{geom}')) RETURNING id") end geo_object[:id] = reply[0]['id'] end end if geo_objects.length == 1 geo_objects[0] else geo_objects end end
choose_db(db)
click to toggle source
# File lib/mapplz.rb, line 28 def choose_db(db) db.downcase! fail 'Database type not supported by MapPLZ' unless DATABASES.include?(db) db = 'postgis' if db == 'postgres' || db == 'postgresql' db = 'spatialite' if db == 'sqlite' db = 'mongodb' if db == 'mongo' @db_type = db @db[:type] = db end
code(mapplz_code)
click to toggle source
# File lib/mapplz.rb, line 144 def code(mapplz_code) @code_lines = mapplz_code.gsub("\r", '').split("\n") @code_level = 'toplevel' @button_layers = [] @code_button = 0 @code_layers = [] @code_label = '' @code_color = nil code_line(0) @code_layers end
count(where_clause = nil, add_on = nil)
click to toggle source
# File lib/mapplz.rb, line 80 def count(where_clause = nil, add_on = nil) results = query(where_clause, add_on) results.length end
embed_html(options = {})
click to toggle source
# File lib/mapplz.rb, line 184 def embed_html(options = {}) # Leaflet options options[:tile_layer] ||= Leaflet.tile_layer options[:attribution] ||= Leaflet.attribution options[:max_zoom] ||= Leaflet.max_zoom options[:container_id] ||= 'map' geojson_features = JSON.parse(to_geojson)['features'] # use Leaflet to add clickable markers options[:markers] = [] geojson_features.each do |feature| next if feature['geometry']['type'] != 'Point' if feature.key?('properties') if feature['properties'].is_a?(Hash) && feature['properties'].key?('label') label = feature['properties']['label'] elsif feature['properties'].key?('properties') && feature['properties']['properties'].is_a?(Array) && feature['properties']['properties'].length == 1 label = feature['properties']['properties'][0] end else label = nil end options[:markers] << { latlng: feature['geometry']['coordinates'].reverse, popup: label } end render_text = map(options).gsub('</script>', '') # add clickable lines and polygons after # Leaflet-Rails does not support clickable lines or any polygons geojson_features.each do |feature| next if feature['geometry']['type'] == 'Point' label = nil path_options = {} path_options[:color] = options[:color] if options.key?(:color) path_options[:opacity] = options[:opacity] if options.key?(:opacity) path_options[:fillColor] = options[:fillColor] if options.key?(:fillColor) path_options[:fillOpacity] = options[:fillOpacity] if options.key?(:fillOpacity) path_options[:weight] = options[:weight] if options.key?(:weight) path_options[:stroke] = options[:stroke] if options.key?(:stroke) if feature.key?('properties') if feature['properties'].key?('label') label = feature['properties']['label'] elsif feature['properties'].key?('properties') && feature['properties']['properties'].is_a?(Array) && feature['properties']['properties'].length == 1 label = feature['properties']['properties'][0] end path_options[:color] = feature['properties']['color'] if feature['properties'].key?('color') path_options[:opacity] = feature['properties']['opacity'].to_f if feature['properties'].key?('opacity') path_options[:fillColor] = feature['properties']['fillColor'] if feature['properties'].key?('fillColor') path_options[:fillOpacity] = feature['properties']['fillOpacity'].to_f if feature['properties'].key?('fillOpacity') path_options[:weight] = feature['properties']['weight'].to_i if feature['properties'].key?('weight') path_options[:stroke] = feature['properties']['stroke'] if feature['properties'].key?('stroke') path_options[:clickable] = true unless label.nil? end flip_coordinates = feature['geometry']['coordinates'] if flip_coordinates[0][0].is_a?(Array) flip_coordinates.each do |segment| segment.map! { |coord| coord.reverse } end else flip_coordinates.map! { |coord| coord.reverse } end if feature['geometry']['type'] == 'LineString' render_text += ('line = L.polyline(' + flip_coordinates.to_json + ", #{path_options.to_json}).addTo(map);\n").html_safe render_text += "line.bindPopup('#{label}');\n".html_safe unless label.nil? elsif feature['geometry']['type'] == 'Polygon' render_text += ('polygon = L.polygon(' + flip_coordinates[0].to_json + ", #{path_options.to_json}).addTo(map);\n").html_safe render_text += "polygon.bindPopup('#{label}');\n".html_safe unless label.nil? end end render_text + '</script>' end
inside(user_geo)
click to toggle source
# File lib/mapplz.rb, line 301 def inside(user_geo) geo_results = [] # accept [point1, point2, point3, point1] as a polygon search area if user_geo.is_a?(Array) && user_geo[0].is_a?(Array) && !user_geo[0][0].is_a?(Array) user_geo = [user_geo] end search_areas = MapPLZ.standardize_geo(user_geo) search_areas.each do |search_area| next unless search_area.key?(:path) wkt = search_area.to_wkt if @db_type == 'array' # in-Ruby point-in-polygon @my_array.each do |geo_item| GeoItem.centroid(geo_item) geo_results << geo_item if geo_item.inside?(search_area) end elsif @db_type == 'mongodb' polygon_gj = JSON.parse(search_area.to_geojson)['geometry'] cursor = @db_client.find(geo: { '$geoWithin' => { '$geometry' => polygon_gj } }) elsif @db_type == 'postgis' cursor = @db_client.exec("SELECT id, ST_AsText(geom) AS geo, properties FROM mapplz AS start WHERE ST_Contains(ST_GeomFromText('#{wkt}'), start.geom)") elsif @db_type == 'spatialite' cursor = @db_client.exec("SELECT id, AsText(geom) AS geo, label FROM mapplz WHERE MBRContains(FromText('#{wkt}'), FromText(geom))") end geo_results += read_cursor(cursor) end geo_results end
length(where_clause = nil, add_on = nil)
click to toggle source
# File lib/mapplz.rb, line 701 def length(where_clause = nil, add_on = nil) count(where_clause, add_on) end
near(user_geo, limit = 10, max = 40_010_000, lon_lat = false)
click to toggle source
# File lib/mapplz.rb, line 263 def near(user_geo, limit = 10, max = 40_010_000, lon_lat = false) max = max.to_f # send max in meters limit = limit.to_i if user_geo.is_a?(Hash) lat = user_geo[:lat] || user_geo['lat'] || user_geo[:latitude] || user_geo['latitude'] lng = user_geo[:lng] || user_geo['lng'] || user_geo[:longitude] || user_geo['longitude'] user_geo = [lat.to_f, lng.to_f] elsif user_geo.is_a?(Array) user_geo.reverse! if lon_lat else fail 'must query near a point' end lat = user_geo[0].to_f lng = user_geo[1].to_f wkt = "POINT(#{lng} #{lat})" geo_results = [] if @db_type == 'array' @my_array.sort! do |a, b| a_distance = a.distance_from([lat, lng]) b_distance = b.distance_from([lat, lng]) a_distance <=> b_distance end geo_results = @my_array.slice(0, limit) elsif @db_type == 'mongodb' cursor = @db_client.find(geo: { '$nearSphere' => { '$geometry' => { type: 'Point', coordinates: [lng, lat] }, '$maxDistance' => max } }) elsif @db_type == 'postgis' cursor = @db_client.exec("SELECT id, ST_AsText(geom) AS geo, properties, ST_Distance(start.geom::geography, ST_GeomFromText('#{wkt}')::geography) AS distance FROM mapplz AS start WHERE ST_Distance(start.geom::geography, ST_GeomFromText('#{wkt}')::geography) <= #{max} ORDER BY distance LIMIT #{limit}") elsif @db_type == 'spatialite' cursor = @db_client.execute("SELECT id, AsText(geom) AS geo, label, Distance(start.geom, AsText('#{wkt}')) AS distance FROM mapplz AS start WHERE Distance(start.geom, AsText('#{wkt}')) <= #{max} ORDER BY distance LIMIT #{limit}") end geo_results += read_cursor(cursor) geo_results end
push(user_geo)
click to toggle source
# File lib/mapplz.rb, line 687 def push(user_geo) add(user_geo) end
query(where_clause = nil, add_on = nil)
click to toggle source
# File lib/mapplz.rb, line 85 def query(where_clause = nil, add_on = nil) geo_results = [] if where_clause.present? if @db_type == 'array' geo_results = query_array(where_clause, add_on) elsif @db_type == 'mongodb' conditions = parse_sql(where_clause, add_on = nil) mongo_conditions = {} conditions.each do |condition| field = condition[:field] compare_value = add_on || condition[:value] operator = condition[:operator].to_s mongo_conditions[field] = compare_value if operator == '=' mongo_conditions[field] = { '$lt' => compare_value } if operator == '<' mongo_conditions[field] = { '$lte' => compare_value } if operator == '<=' mongo_conditions[field] = { '$gt' => compare_value } if operator == '>' mongo_conditions[field] = { '$gte' => compare_value } if operator == '>=' end cursor = @db_client.find(mongo_conditions) elsif @db_type == 'postgis' conditions = parse_sql(where_clause, add_on = nil) conditions.each do |condition| where_prop = condition[:field].to_s where_clause = where_clause.gsub(where_prop, "json_extract_path_text(properties, '#{where_prop}')") end cursor = @db_client.exec("SELECT id, ST_AsText(geom) AS geo, properties FROM mapplz WHERE #{where_clause}") elsif @db_type == 'spatialite' if add_on.is_a?(String) where_clause = where_clause.gsub('?', "'#{add_on}'") elsif add_on.is_a?(Integer) || add_on.is_a?(Float) where_clause = where_clause.gsub('?', "#{add_on}") end cursor = @db_client.execute("SELECT id, AsText(geom) AS geo, label FROM mapplz WHERE #{where_clause}") end else # query all if @db_type == 'array' geo_results = @my_array elsif @db_type == 'mongodb' cursor = @db_client.find elsif @db_type == 'postgis' cursor = @db_client.exec('SELECT id, ST_AsText(geom) AS geo, properties FROM mapplz') elsif @db_type == 'spatialite' cursor = @db_client.execute('SELECT id, AsText(geom) AS geo, label FROM mapplz') else # @my_db.all end end geo_results += read_cursor(cursor) geo_results end
render_html(options = {})
click to toggle source
# File lib/mapplz.rb, line 161 def render_html(options = {}) my_embed = embed_html(options) my_embed = "<!DOCTYPE html> <html> <head> <style type=\"text/css\"> html, body, #map { width: 100%; height: 100%; margin: 0; padding: 0; } </style> <script type=\"text/javascript\" src=\"http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js\"></script> <link href=\"http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css\" rel=\"stylesheet\" type=\"text/css\"/> </head> <body> #{my_embed} </body> </html>" my_embed end
size(where_clause = nil, add_on = nil)
click to toggle source
aliases for count
# File lib/mapplz.rb, line 697 def size(where_clause = nil, add_on = nil) count(where_clause, add_on) end
to_geojson()
click to toggle source
# File lib/mapplz.rb, line 156 def to_geojson geojson = { type: 'FeatureCollection', features: query.map { |feature| JSON.parse(feature.to_geojson) } } geojson.to_json end
where(where_clause = nil, add_on = nil)
click to toggle source
aliases for query
# File lib/mapplz.rb, line 692 def where(where_clause = nil, add_on = nil) query(where_clause, add_on) end
Private Instance Methods
code_line(index)
click to toggle source
# File lib/mapplz.rb, line 927 def code_line(index) return if index >= @code_lines.length line = @code_lines[index].strip codeline = line.downcase.split(' ') if @code_level == 'toplevel' @code_level = 'map' if line.index('map') return code_line(index + 1) elsif @code_level == 'map' || @code_level == 'button' if codeline.index('button') || codeline.index('btn') @code_level = 'button' @button_layers << { layers: [] } @code_button = @button_layers.length end if codeline.index('marker') @code_level = 'marker' @code_latlngs = [] return code_line(index + 1) elsif codeline.index('line') @code_level = 'line' @code_latlngs = [] return code_line(index + 1) elsif codeline.index('shape') @code_level = 'shape' @code_latlngs = [] return code_line(index + 1) end if codeline.index('plz') || codeline.index('please') if @code_level == 'map' @code_level = 'toplevel' return elsif @code_level == 'button' # add button @code_level = 'map' @code_button = nil return code_line(index + 1) end end elsif @code_level == 'marker' || @code_level == 'line' || @code_level == 'shape' if codeline.index('plz') || codeline.index('please') if @code_level == 'marker' geoitem = GeoItem.new(@db) geoitem[:lat] = @code_latlngs[0][0] geoitem[:lng] = @code_latlngs[0][1] geoitem[:label] = @code_label || '' @code_layers << geoitem elsif @code_level == 'line' geoitem = GeoItem.new(@db) geoitem[:path] = @code_latlngs geoitem[:stroke_color] = (@code_color || '') geoitem[:label] = @code_label || '' @code_layers << geoitem elsif @code_level == 'shape' geoitem = GeoItem.new(@db) geoitem[:paths] = @code_latlngs geoitem[:stroke_color] = (@code_color || '') geoitem[:fill_color] = (@code_color || '') geoitem[:label] = @code_label || '' @code_layers << geoitem end if @code_button @code_level = 'button' else @code_level = 'map' end @code_latlngs = [] return code_line(index + 1) end end # geocoding starts with @ # reading a color if codeline[0].index('#') == 0 @code_color = codeline[0] if @code_color.length != 4 && @code_color.length != 7 # named color @code_color = @code_color.gsub('#', '') end if @code_level == 'button' # button color end return codeline(index + 1) end # reading a raw string (probably text for a popup) if codeline[0].index('"') == 0 # check button @code_label = line[(line.index('"') + 1)..line.length] @code_label = @code_label[0..(@code_label.index('"') - 1)] end # reading a latlng coordinate if line.index('[') && line.index(',') && line.index(']') latlng_line = line.gsub('[', '').gsub(']', '').split(',').map! { |num| num.to_f } # must be a 2D coordinate return codeline(index + 1) if latlng_line.length != 2 @code_latlngs << latlng_line return code_line(index + 1) end code_line(index + 1) end
parse_sql(where_clause, add_on = nil)
click to toggle source
# File lib/mapplz.rb, line 1047 def parse_sql(where_clause, add_on = nil) where_clause.downcase! unless where_clause.blank? where_clause = where_clause.gsub('?', '\'?\'') if add_on.present? where_clause = 'select * from bogus_table where ' + where_clause # parse where conditions @parser.parse(where_clause).tree[:conditions] end
query_array(where_clause, add_on = nil)
click to toggle source
# File lib/mapplz.rb, line 1056 def query_array(where_clause, add_on = nil) # prepare where clause for parse conditions = parse_sql(where_clause, add_on) # filter array @my_array.select do |geo_obj| return false if geo_obj.nil? is_valid = true conditions.each do |condition| field = condition[:field] compare_value = add_on || condition[:value] operator = condition[:operator].to_s # check that key exists is_valid = geo_obj.key?(field) break unless is_valid # compare to value if operator == '<' is_valid = geo_obj[field] < compare_value elsif operator == '<=' is_valid = geo_obj[field] <= compare_value elsif operator == '>' is_valid = geo_obj[field] > compare_value elsif operator == '>=' is_valid = geo_obj[field] >= compare_value elsif operator == '=' is_valid = geo_obj[field] == compare_value else fail "#{operator} comparison not supported by MapPLZ on arrays" end break unless is_valid end is_valid end end
read_cursor(cursor)
click to toggle source
# File lib/mapplz.rb, line 892 def read_cursor(cursor) if cursor.nil? [] else geo_results = [] cursor.each do |geo_result| if @db_type == 'postgis' geo_item = GeoItem.new(@db) geom = (geo_result['geo'] || geo_result[:geo]).upcase geo_item = MapPLZ.parse_wkt(geo_item, geom) geo_result = JSON.parse(geo_result['properties']) elsif @db_type == 'spatialite' geo_item = GeoItem.new(@db) geom = (geo_result['geo'] || geo_result[:geo]).upcase geo_item = MapPLZ.parse_wkt(geo_item, geom) elsif @db_type == 'mongodb' geom = { 'type' => 'Feature', 'geometry' => geo_result['geo'] } geo_item = MapPLZ.standardize_geo(geom, true, @db)[0] end if geo_result.is_a?(Array) geo_item[:properties] = geo_result else geo_result.keys.each do |key| next if [:geo].include?(key.to_sym) geo_item[key.to_sym] = geo_result[key] end end geo_results << geo_item end geo_results end end