Module: SpatialFeatures::ClassMethods
- Defined in:
- lib/spatial_features/has_spatial_features.rb
Instance Method Summary collapse
- #cached_spatial_join(other) ⇒ Object
-
#features_cache_key ⇒ Object
NOTE: features are never updated, only deleted and created, therefore we can tell if they have changed by finding the maximum id and count instead of needing timestamps.
- #intersecting(other, options = {}) ⇒ Object
- #joins_features(table_alias = 'features_for') ⇒ Object
- #joins_features_for(other, table_alias = 'features_for') ⇒ Object
- #lines ⇒ Object
- #points ⇒ Object
- #polygons ⇒ Object
- #within_buffer(other, buffer_in_meters = 0, options = {}) ⇒ Object
Instance Method Details
#cached_spatial_join(other) ⇒ Object
62 63 64 65 66 67 68 69 |
# File 'lib/spatial_features/has_spatial_features.rb', line 62 def cached_spatial_join(other) raise "Cannot use cached spatial join for the same class" if other.class.name == self.name other_column = other.class.name < self.name ? :model_a : :model_b self_column = other_column == :model_a ? :model_b : :model_a joins("INNER JOIN spatial_proximities ON spatial_proximities.#{self_column}_type = '#{self}' AND spatial_proximities.#{self_column}_id = #{table_name}.id AND spatial_proximities.#{other_column}_type = '#{other.class}' AND spatial_proximities.#{other_column}_id = '#{other.id}'") end |
#features_cache_key ⇒ Object
NOTE: features are never updated, only deleted and created, therefore we can tell if they have changed by finding the maximum id and count instead of needing timestamps
21 22 23 |
# File 'lib/spatial_features/has_spatial_features.rb', line 21 def features_cache_key "#{name}/#{Feature.where(:spatial_model_type => self).maximum(:id)}-#{Feature.where(:spatial_model_type => self).count}" end |
#intersecting(other, options = {}) ⇒ Object
25 26 27 |
# File 'lib/spatial_features/has_spatial_features.rb', line 25 def intersecting(other, = {}) within_buffer(other, 0, ) end |
#joins_features(table_alias = 'features_for') ⇒ Object
76 77 78 |
# File 'lib/spatial_features/has_spatial_features.rb', line 76 def joins_features(table_alias = 'features_for') joins(%Q(INNER JOIN features "#{table_alias}" ON "#{table_alias}".spatial_model_type = '#{name}' AND "#{table_alias}".spatial_model_id = #{table_name}.id)) end |
#joins_features_for(other, table_alias = 'features_for') ⇒ Object
71 72 73 74 |
# File 'lib/spatial_features/has_spatial_features.rb', line 71 def joins_features_for(other, table_alias = 'features_for') joins_features(table_alias) .joins(%Q(INNER JOIN features "#{table_alias}_other" ON "#{table_alias}_other".spatial_model_type = '#{other.class.name}' AND "#{table_alias}_other".spatial_model_id = #{other.id})) end |
#lines ⇒ Object
54 55 56 |
# File 'lib/spatial_features/has_spatial_features.rb', line 54 def lines Feature.lines.where(:spatial_model_type => self.class) end |
#points ⇒ Object
58 59 60 |
# File 'lib/spatial_features/has_spatial_features.rb', line 58 def points Feature.points.where(:spatial_model_type => self.class) end |
#polygons ⇒ Object
50 51 52 |
# File 'lib/spatial_features/has_spatial_features.rb', line 50 def polygons Feature.polygons.where(:spatial_model_type => self.class) end |
#within_buffer(other, buffer_in_meters = 0, options = {}) ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/spatial_features/has_spatial_features.rb', line 29 def within_buffer(other, buffer_in_meters = 0, = {}) raise "Can't intersect with #{other} because it does not implement has_features" unless other.has_spatial_features? if other.spatial_cache_for?(self, buffer_in_meters) && [:cache] != false # CACHED scope = cached_spatial_join(other) .select("#{table_name}.*, spatial_proximities.distance_in_meters, spatial_proximities.intersection_area_in_square_meters") scope = scope.where("spatial_proximities.distance_in_meters <= ?", buffer_in_meters) if buffer_in_meters else # NON-CACHED scope = joins_features_for(other) .select("#{table_name}.*") .group("#{table_name}.#{primary_key}") scope = scope.where('ST_DWithin(features_for.geog, features_for_other.geog, ?)', buffer_in_meters) if buffer_in_meters scope = scope.select("MIN(ST_Distance(features_for.geog, features_for_other.geog)) AS distance_in_meters") if [:distance] scope = scope.select("SUM(ST_Area(ST_Intersection(features_for.geog, features_for_other.geog))) AS intersection_area_in_square_meters") if [:intersection_area] end return scope end |