diff --git a/app/controllers/carto/api/visualization_searcher.rb b/app/controllers/carto/api/visualization_searcher.rb index 74d45dff1e..8f69d8dea3 100644 --- a/app/controllers/carto/api/visualization_searcher.rb +++ b/app/controllers/carto/api/visualization_searcher.rb @@ -1,4 +1,4 @@ -require_relative '../../../helpers/bounding_box_helper' +require_relative '../../../helpers/bounding_box_utils' module Carto module Api @@ -40,7 +40,7 @@ module Carto .with_tags(tags) if !bbox_parameter.blank? - vqb.with_bounding_box(BoundingBoxHelper.new.parse_bbox_parameters(bbox_parameter)) + vqb.with_bounding_box(BoundingBoxUtils.parse_bbox_parameters(bbox_parameter)) end # FIXME Patch to exclude legacy visualization from data-library #5097 diff --git a/app/models/map.rb b/app/models/map.rb index 2313e0fffb..704a6374a4 100644 --- a/app/models/map.rb +++ b/app/models/map.rb @@ -1,7 +1,6 @@ # encoding: utf-8 require_relative '../models/visualization/collection' require_relative '../models/table/user_table' -require_relative '../helpers/bounding_box_helper' require_dependency 'common/map_common' class Map < Sequel::Model diff --git a/app/queries/carto/visualization_query_builder.rb b/app/queries/carto/visualization_query_builder.rb index 992a34e16a..ba73725e12 100644 --- a/app/queries/carto/visualization_query_builder.rb +++ b/app/queries/carto/visualization_query_builder.rb @@ -312,7 +312,7 @@ class Carto::VisualizationQueryBuilder end if @bounding_box - bbox_sql = BoundingBoxHelper.to_polygon(@bounding_box[:minx], @bounding_box[:miny], @bounding_box[:maxx], @bounding_box[:maxy]) + bbox_sql = BoundingBoxUtils.to_polygon(@bounding_box[:minx], @bounding_box[:miny], @bounding_box[:maxx], @bounding_box[:maxy]) query = query.where("visualizations.bbox is not null AND visualizations.bbox && #{bbox_sql}") end diff --git a/lib/carto/bounding_box_service.rb b/lib/carto/bounding_box_service.rb index a3b7bd7150..a9dae9c5f8 100644 --- a/lib/carto/bounding_box_service.rb +++ b/lib/carto/bounding_box_service.rb @@ -4,13 +4,6 @@ require_relative '../../lib/carto/table_utils' class Carto::BoundingBoxService extend Carto::TableUtils - DEFAULT_BOUNDS = { - minx: -179, - maxx: 179, - miny: -85.0511, - maxy: 85.0511 - }.freeze - def initialize(user) @user = user end @@ -20,10 +13,10 @@ class Carto::BoundingBoxService result = current_bbox_using_stats(table_name) return nil unless result { - maxx: bound_for(result[:max][0].to_f, :minx, :maxx), - maxy: bound_for(result[:max][1].to_f, :miny, :maxy), - minx: bound_for(result[:min][0].to_f, :minx, :maxx), - miny: bound_for(result[:min][1].to_f, :miny, :maxy) + maxx: BoundingBoxUtils.bound_for(result[:max][0].to_f, :minx, :maxx), + maxy: BoundingBoxUtils.bound_for(result[:max][1].to_f, :miny, :maxy), + minx: BoundingBoxUtils.bound_for(result[:min][0].to_f, :minx, :maxx), + miny: BoundingBoxUtils.bound_for(result[:min][1].to_f, :miny, :maxy) } end @@ -66,10 +59,6 @@ class Carto::BoundingBoxService raise BoundingBoxError.new("Can't calculate the bounding box for table #{table_name}. ERROR: #{exception}") end - def bound_for(value, minimum, maximum) - [[value, DEFAULT_BOUNDS.fetch(minimum)].max, DEFAULT_BOUNDS.fetch(maximum)].min - end - def get_bbox_values(table_name, column_name) result = @user.service.execute_in_user_database(%{ SELECT diff --git a/lib/carto/bounding_box_utils.rb b/lib/carto/bounding_box_utils.rb new file mode 100644 index 0000000000..786b3533a6 --- /dev/null +++ b/lib/carto/bounding_box_utils.rb @@ -0,0 +1,38 @@ +module Carto::BoundingBoxUtils + DEFAULT_BOUNDS = { + minx: -179, + maxx: 179, + miny: -85.0511, + maxy: 85.0511 + }.freeze + + def self.bound_for(value, minimum, maximum) + [[value, DEFAULT_BOUNDS.fetch(minimum)].max, DEFAULT_BOUNDS.fetch(maximum)].min + end + + def self.to_polygon(minx, miny, maxx, maxy) + return nil unless check_bounds_for(minx, miny) && check_bounds_for(maxx, maxy) + %{ST_Transform(ST_Envelope('SRID=4326;POLYGON((#{minx} #{miny}, #{minx} #{maxy}, #{maxx} #{maxy}, #{maxx} #{miny}, #{minx} #{miny}))'::geometry), 3857)} + end + + def self.to_point(x, y) + return nil unless check_bounds_for(x, y) + %[ST_GeomFromText('POINT(#{x} #{y})',3857)] + end + + def self.parse_bbox_parameters(bounding_box) + bbox_coords = bounding_box.split(',').map { |coord| Float(coord) rescue nil }.compact + if bbox_coords.length != 4 + raise CartoDB::BoundingBoxError.new('bounding box must have 4 coordinates: minx, miny, maxx, maxy') + end + { minx: bbox_coords[0], miny: bbox_coords[1], maxx: bbox_coords[2], maxy: bbox_coords[3] } + end + + def self.check_bounds_for(x, y) + return false if x.to_f > LIMIT_BOUNDS[:maxlon].to_f || x.to_f < LIMIT_BOUNDS[:minlon].to_f + return false if y.to_f > LIMIT_BOUNDS[:maxlat].to_f || y.to_f < LIMIT_BOUNDS[:minlat].to_f + true + rescue + false + end +end diff --git a/lib/explore_api.rb b/lib/explore_api.rb index 17c7983fed..8ce1a25a67 100644 --- a/lib/explore_api.rb +++ b/lib/explore_api.rb @@ -26,10 +26,10 @@ class ExploreAPI center_coordinates = map.center_data.reverse { zoom: map.zoom, - view_box_polygon: BoundingBoxHelper.to_polygon( + view_box_polygon: Carto::BoundingBoxUtils.to_polygon( view_box[:west], view_box[:south], view_box[:east], view_box[:north] ), - center_geometry: BoundingBoxHelper.to_point(center_coordinates[0], center_coordinates[1]) + center_geometry: Carto::BoundingBoxUtils.to_point(center_coordinates[0], center_coordinates[1]) } end diff --git a/spec/models/map_spec.rb b/spec/models/map_spec.rb index 0d983cc19a..e7f1859a78 100644 --- a/spec/models/map_spec.rb +++ b/spec/models/map_spec.rb @@ -176,23 +176,23 @@ describe Map do value5 = -180 value6 = 0 - BoundingBoxHelper.bound_for(value1, min_value, max_value).should eq value1 - BoundingBoxHelper.bound_for(value2, min_value, max_value).should eq value2 - BoundingBoxHelper.bound_for(value2, min_value, max_value).should eq BoundingBoxHelper::DEFAULT_BOUNDS[max_value] - BoundingBoxHelper.bound_for(value3, min_value, max_value).should eq value3 - BoundingBoxHelper.bound_for(value3, min_value, max_value).should eq BoundingBoxHelper::DEFAULT_BOUNDS[min_value] - BoundingBoxHelper.bound_for(value4, min_value, max_value).should eq BoundingBoxHelper::DEFAULT_BOUNDS[max_value] - BoundingBoxHelper.bound_for(value5, min_value, max_value).should eq BoundingBoxHelper::DEFAULT_BOUNDS[min_value] - BoundingBoxHelper.bound_for(value6, min_value, max_value).should eq value6 + Carto::BoundingBoxUtils.bound_for(value1, min_value, max_value).should eq value1 + Carto::BoundingBoxUtils.bound_for(value2, min_value, max_value).should eq value2 + Carto::BoundingBoxUtils.bound_for(value2, min_value, max_value).should eq Carto::BoundingBoxUtils::DEFAULT_BOUNDS[max_value] + Carto::BoundingBoxUtils.bound_for(value3, min_value, max_value).should eq value3 + Carto::BoundingBoxUtils.bound_for(value3, min_value, max_value).should eq Carto::BoundingBoxUtils::DEFAULT_BOUNDS[min_value] + Carto::BoundingBoxUtils.bound_for(value4, min_value, max_value).should eq Carto::BoundingBoxUtils::DEFAULT_BOUNDS[max_value] + Carto::BoundingBoxUtils.bound_for(value5, min_value, max_value).should eq Carto::BoundingBoxUtils::DEFAULT_BOUNDS[min_value] + Carto::BoundingBoxUtils.bound_for(value6, min_value, max_value).should eq value6 # As map has no geometries, bounds should still be default ones instead of zeros map_bounds = new_map.send(:get_map_bounds) - default_bounds = BoundingBoxHelper.default_bbox + default_bounds = Carto::BoundingBoxUtils.DEFAULT_BOUNDS - map_bounds[:maxx].should eq default_bounds[:max][0] - map_bounds[:maxy].should eq default_bounds[:max][1] - map_bounds[:minx].should eq default_bounds[:min][0] - map_bounds[:miny].should eq default_bounds[:min][1] + map_bounds[:maxx].should eq default_bounds[:maxx] + map_bounds[:maxy].should eq default_bounds[:maxy] + map_bounds[:minx].should eq default_bounds[:minx] + map_bounds[:miny].should eq default_bounds[:miny] new_map.destroy