+ def self.from_s(s)
+ if s.count(',') == 3
+ BoundingBox.new(*s.split(/,/))
+ else
+ nil
+ end
+ end
+
+ def self.from_bbox_params(params)
+ if params[:bbox] and params[:bbox].count(',') == 3
+ bbox_array = params[:bbox].split(',')
+ end
+ from_bbox_array(bbox_array)
+ end
+
+ def self.from_lon_lat_params(params)
+ if params[:minlon] and params[:minlat] and params[:maxlon] and params[:maxlat]
+ bbox_array = [params[:minlon], params[:minlat], params[:maxlon], params[:maxlat]]
+ end
+ from_bbox_array(bbox_array)
+ end
+
+ def self.from_lrbt_params(params)
+ if params[:l] and params[:b] and params[:t] and params[:t]
+ bbox_array = [params[:l], params[:b], params[:r], params[:t]]
+ end
+ from_bbox_array(bbox_array)
+ end
+
+ def expand!(bbox, margin = 0)
+ update!(bbox) unless complete?
+ # only try to expand the bbox if there is a value for every coordinate
+ # which there will be from the previous line as long as array does not contain a nil
+ if bbox.complete?
+ @min_lon = [-SCALED_LON_LIMIT,
+ bbox.min_lon + margin * (min_lon - max_lon)].max if bbox.min_lon < min_lon
+ @min_lat = [-SCALED_LAT_LIMIT,
+ bbox.min_lat + margin * (min_lat - max_lat)].max if bbox.min_lat < min_lat
+ @max_lon = [+SCALED_LON_LIMIT,
+ bbox.max_lon + margin * (max_lon - min_lon)].min if bbox.max_lon > max_lon
+ @max_lat = [+SCALED_LAT_LIMIT,
+ bbox.max_lat + margin * (max_lat - min_lat)].min if bbox.max_lat > max_lat
+ end
+ self
+ end
+
+ def check_boundaries
+ # check the bbox is sane
+ if min_lon > max_lon
+ raise OSM::APIBadBoundingBox.new(
+ "The minimum longitude must be less than the maximum longitude, but it wasn't")
+ end
+ if min_lat > max_lat
+ raise OSM::APIBadBoundingBox.new(
+ "The minimum latitude must be less than the maximum latitude, but it wasn't")
+ end
+ if min_lon < -LON_LIMIT || min_lat < -LAT_LIMIT || max_lon > +LON_LIMIT || max_lat > +LAT_LIMIT
+ raise OSM::APIBadBoundingBox.new("The latitudes must be between #{-LAT_LIMIT} and #{LAT_LIMIT}," +
+ " and longitudes between #{-LON_LIMIT} and #{LON_LIMIT}")
+ end
+ self
+ end
+
+ def check_size(max_area = MAX_REQUEST_AREA)
+ # check the bbox isn't too large
+ if area > max_area
+ raise OSM::APIBadBoundingBox.new("The maximum bbox size is " + max_area.to_s +
+ ", and your request was too large. Either request a smaller area, or use planet.osm")
+ end
+ self
+ end
+
+ ##
+ # returns area of the bbox as a rough comparative quantity
+ def area
+ if complete?
+ (max_lon - min_lon) * (max_lat - min_lat)
+ else
+ 0
+ end
+ end
+
+ def complete?
+ not to_a.include?(nil)