class MapsController < ApplicationController # GET /maps # GET /maps.xml layout 'mapdetail', :except => [:index, :new, :tag] #before_filter :login_required, :only => [:destroy, :delete] before_filter :login_required, :only => [:new, :create, :edit, :update, :destroy, :delete, :warp, :rectify, :clip, :align, :warp_align, :mask_map, :delete_mask, :save_mask, :save_mask_and_warp ] before_filter :check_administrator_role, :only => [:publish] before_filter :find_map_if_available, :except => [:show, :index, :wms, :mapserver_wms, :warp_aligned, :status, :new, :create, :update, :edit, :tag] before_filter :check_link_back, :only => [:show, :warp, :clip, :align, :warped, :activity] before_filter :check_if_map_is_editable, :only => [:edit, :update] before_filter :check_if_map_can_be_deleted, :only => [:destroy, :delete] helper :sort include SortHelper def index sort_init('updated_at', {:default_order => "desc"}) sort_update @show_warped = params[:show_warped] request.query_string.length > 0 ? qstring = "?" + request.query_string : qstring = "" set_session_link_back url_for(:controller=> 'maps', :action => 'index',:skip_relative_url_root => false, :only_path => false )+ qstring @query = params[:query] @field = %w(tags title description status publisher authors).detect{|f| f == (params[:field])} unless @field == "tags" @field = "title" if @field.nil? if @query && @query.strip.length > 0 && @field if @show_warped == "1" conditions = ["upper(#{@field} ) LIKE ? AND status = 4 ", '%'+@query.upcase+'%' ] else conditions = ["upper(#{@field} ) LIKE ? ", '%'+@query.upcase+'%'] end else if @show_warped == "1" conditions = ["status = 4 "] else conditions = nil end end paginate_params = { :page => params[:page], :per_page => 10, :order => sort_clause, :conditions => conditions, :include =>[:gcps,:users] } @maps = (logged_in? and current_user.has_role?("editor")) ? Map.paginate(paginate_params) : Map.public.paginate(paginate_params) @html_title = "Listing All Uploaded Maps on " respond_to do |format| format.html{ render :layout =>'application' } # index.html.erb format.xml { render :xml => @maps } end else redirect_to :action => 'tag', :id => @query end end def tag sort_init('updated_at', {:default_order => "desc"}) sort_update @tags = params[:id] || @query @html_title = "Maps tagged with #{@tags} on " @maps = Map.public.paged_find_tagged_with( @tags, :page => params[:page], :per_page => 20, :order => sort_clause) respond_to do |format| format.html{ render :layout =>'application' } # index.html.erb format.xml { render :xml => @maps } format.rss { render :layout => false } end end def export @current_tab = :export @html_title = "Export Options for #{@map.id} on " respond_to do |format| format.html #export.html.erb end end def new @map = Map.new @html_title = "Upload a new map to " @max_size = Map.max_attachment_size if Map.max_dimension @upload_file_message = " It may resize the image if it's too large (#{Map.max_dimension}x#{Map.max_dimension}) " else @upload_file_message = "" end respond_to do |format| format.html{ render :layout =>'application' } # new.html.erb format.xml { render :xml => @map } end end def create @map = Map.new(params[:map]) if logged_in? @map.owner = current_user @map.users << current_user end respond_to do |format| if @map.save flash[:notice] = 'Map was successfully created.' format.html { redirect_to(@map) } format.xml { render :xml => @map, :status => :created, :location => @map } else format.html { render :action => "new", :layout =>'application' } format.xml { render :xml => @map.errors, :status => :unprocessable_entity } end end end def edit @current_tab = :edit @html_title = "Editing Map #{@map.title} on" respond_to do |format| format.html #{ render :layout =>'application' } # new.html.erb format.xml { render :xml => @map } end end def update #@map = Map.find(params[:id]) respond_to do |format| if @map.update_attributes(params[:map]) flash[:notice] = 'Map was successfully updated.' format.html { redirect_to(@map) } format.xml { head :ok } else format.html { render :action => "edit" } format.xml { render :xml => @map.errors, :status => :unprocessable_entity } end end end def delete respond_to do |format| format.html end end #only editors or owners of maps def destroy if @map.destroy flash[:notice] = "Map deleted!" else flash[:notice] = "Map wasnt deleted" end respond_to do |format| format.html { redirect_to(maps_url) } format.xml { head :ok } end end def status map = Map.find(params[:id]) if map.status.nil? sta = "loading" else sta = map.status.to_s end render :text => sta end def show @current_tab = :show @map = Map.find(params[:id]) unless @map.public? or ( logged_in? and ( current_user.own_this_map?(params[:id]) or current_user.has_role?("editor") ) ) redirect_to maps_path else @html_title = "Showing Map #{@map.title} on " if @map.status.nil? || @map.status == :unloaded @mapstatus = "unloaded" else @mapstatus = @map.status.to_s end if @map.status.nil? or @map.status == :unloaded @disabled_tabs = [:warp, :clip, :align, :warped, :activity] @title = "Viewing unrectified map." render :action => "preview" return end @title = "Viewing original map. " if @map.status != :warped @title += "This map has not been rectified yet." end respond_to do |format| format.html # show.html.erb # choice of kml formats: show_simple for simple png link, show_reflect for nicer wms reflection and show_region for multiscales format.kml { render :action => 'show_reflect', :layout => false } #format.xml { render :xml => @map } end end # end end def clip @html_title = "Crop Map #{@map.title} on " @current_tab = :clip # @map = Map.find(params[:id]) @gml_exists = "false" if File.exists?(@map.masking_file_gml+".ol") @gml_exists = "true" end end #should check for admin only def publish # @map = Map.find(params[:id]) @map.publish render :text => "Map will be published. (this functionality doesn't do anything at the moment)" end def save_mask message = @map.save_mask(params[:output]) render :text => message end def delete_mask message = @map.delete_mask render :text => message end def mask_map message = @map.mask! render :text => message end def warped @html_title = "Warped Map #{@map.title} on " @current_tab = :warped if @map.status == :warped and @map.gcps.size > 2 @title = "Viewing warped map" width = @map.width height = @map.height respond_to do |format| format.html # show.html.erb #format.xml { render :xml => @map } end else flash[:notice] = "Whoops, you have to rectify a map before you can view it" redirect_to :action => "show" end end def warp_aligned destmap = Map.find(params[:destmap]) params[:id] = params[:destmap] align = params[:align].downcase append = params[:append] if params[:align_type] == "original" result = destmap.align_with_original(params[:srcmap], align, append ) else result = destmap.align_with_warped(params[:srcmap], align, append ) end flash[:notice] = "map aligned" redirect_to :action => "warp", :id => destmap.id end def align @current_tab = :align @html_title = "Align Map - " + @map.title width = @map.width height = @map.height end def warp @html_title = "Rectify Map #{@map.title} on " @current_tab = :warp @gcps = @map.gcps_with_error width = @map.width height = @map.height width_ratio = width / 180 height_ratio = height / 90 end def save_mask_and_warp logger.info "save mask and warp" if params[:output].blank? render :text => "Map not masked, have you drawn one on the map?" else @map.save_mask(params[:output]) @map.mask! if @map.gcps.size.nil? || @map.gcps.size < 3 render :text => "Map masked, but it needs more control points to rectify. Click the Rectify tab to add some." else params[:use_mask] = "true" rectify #which gives us @rectify_success unless @rectify_success == true render :text => "Something went wrong rectifying the map." else render :text => "Map masked and rectified!" end end end end def rectify #gotta catch if user submits and there are no GCP's entered - done :) #also ##catch if user submits a blank GCP. Message about minimum 3 ? #logger.info params.inspect resample_param = params[:resample_options] transform_param = params[:transform_options] masking_option = params[:mask] resample_option = "" transform_option = "" case transform_param when "auto" transform_option = "" when "p1" transform_option = " -order 1 " when "p2" transform_option = " -order 2 " when "p3" transform_option = " -order 3 " when "tps" transform_option = " -tps " else transform_option = "" end case resample_param when "near" resample_option = " -rn " when "bilinear" resample_option = " -rb " when "cubic" resample_option = " -rc " when "cubicspline" resample_option = " -rcs " when "lanczos" #its very very slow resample_option = " -rn " else resample_option = " -rn" end use_mask = params[:use_mask] @too_few = false if @map.gcps.size.nil? || @map.gcps.size < 3 @too_few = true @notice_text = "Sorry, the map needs at least three control points to be able to rectify it" @output = @notice_text else if logged_in? um = current_user.my_maps.new(:map => @map) um.save # @map.users << current_user # another way creating the relationship end if @map.warp! transform_option, resample_option, use_mask #,masking_option @notice_text = "Map rectified!" @rectify_success = true else @notice_text = "Something went wrong rectifying the map." @rectify_success = false end redirect_to :action=> :index unless request.xhr? end end ################################################# #MAPSERVER methods. #Checks to see if mapscript is available, then redirects to cgi, or does it itself. ############################################### begin include Mapscript if require 'mapscript' @@mapscript_exists = true #YES, this means that all requests will go to cgi (seems quicker) rescue LoadError @@mapscript_exists = false #YES, this means that all requests will go to cgi (seems quicker) end def wms unless @@mapscript_exists mapserver_wms else @map = Map.find(params[:id]) #status is additional query param to show the unwarped wms status = params["STATUS"].to_s.downcase || "unwarped" ows = Mapscript::OWSRequest.new ok_params = Hash.new # params.each {|k,v| k.upcase! } frozen string error params.each {|k,v| ok_params[k.upcase] = v } [:request, :version, :transparency, :service, :srs, :width, :height, :bbox, :format, :srs].each do |key| ows.setParameter(key.to_s, ok_params[key.to_s.upcase]) unless ok_params[key.to_s.upcase].nil? end ows.setParameter("STYLES", "") ows.setParameter("LAYERS", "image") ows.setParameter("COVERAGE", "image") mapsv = Mapscript::MapObj.new(File.join(RAILS_ROOT, '/db/maptemplates/wms.map')) projfile = File.join(RAILS_ROOT, '/lib/proj') mapsv.setConfigOption("PROJ_LIB", projfile) #map.setProjection("init=epsg:900913") mapsv.applyConfigOptions rel_url_root = (ActionController::Base.relative_url_root.blank?)? '' : ActionController::Base.relative_url_root mapsv.setMetaData("wms_onlineresource", "http://" + request.host_with_port + rel_url_root + "/maps/wms/#{@map.id}") raster = Mapscript::LayerObj.new(mapsv) raster.name = "image" raster.type = Mapscript::MS_LAYER_RASTER if status == "unwarped" raster.data = @map.unwarped_filename else #show the warped map raster.data = @map.warped_filename end raster.status = Mapscript::MS_ON raster.dump = Mapscript::MS_TRUE raster.metadata.set('wcs_formats', 'GEOTIFF') raster.metadata.set('wms_title', @map.title) raster.metadata.set('wms_srs', 'EPSG:4326 EPSG:4269 EPSG:900913') raster.debug = Mapscript::MS_TRUE Mapscript::msIO_installStdoutToBuffer result = mapsv.OWSDispatch(ows) content_type = Mapscript::msIO_stripStdoutBufferContentType || "text/plain" result_data = Mapscript::msIO_getStdoutBufferBytes send_data result_data, :type => content_type, :disposition => "inline" Mapscript::msIO_resetHandlers end end ################################### #private ################################## private def mapserver_wms #use Map.map_file_path so we don't have to do a db call status = params["STATUS"].to_s.downcase || "unwarped" styles = "&styles=" # required to stop mapserver being pedantic on older versions if status == "unwarped" mapserver_url = MAPSERVER_URL + '?map=' + Map.mapfile_path(params[:id]) + styles + "&layers=" + params[:id].to_s + "_original" else mapserver_url = MAPSERVER_URL + '?map=' + Map.mapfile_path(params[:id]) + styles + "&layers=" + params[:id].to_s end mapserver_url += "&"+request.query_string redirect_to(mapserver_url) end def set_session_link_back link_url session[:link_back] = link_url end def check_link_back @link_back = session[:link_back] if @link_back.nil? @link_back = url_for(:action => 'index') end session[:link_back] = @link_back end #only allow deleting by a user if the user owns it def check_if_map_can_be_deleted if logged_in? and (current_user.own_this_map?(params[:id]) or current_user.has_role?("editor")) @map = Map.find(params[:id]) else flash[:notice] = "Sorry, you cannot delete other people's maps!" redirect_to map_path end end #only allow editing by a user if the user owns it, or if and editor tries to edit it def check_if_map_is_editable if logged_in? and (current_user.own_this_map?(params[:id]) or current_user.has_role?("editor")) @map = Map.find(params[:id]) elsif Map.find(params[:id]).owner.nil? @map = Map.find(params[:id]) else flash[:notice] = "Sorry, you cannot edit other people's maps" redirect_to map_path end end def find_map_if_available @map = Map.find(params[:id]) if @map.status.nil? or @map.status == :unloaded or @map.status == :loading redirect_to map_path elsif (!@map.public? and !logged_in?) or((!@map.public? and logged_in?) and !(current_user.own_this_map?(params[:id]) or current_user.has_role?("editor")) ) redirect_to maps_path end end end