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
65 66 67 68 69 70 71 72 |
# File 'lib/spatial_features/has_spatial_features.rb', line 65 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 24 |
# File 'lib/spatial_features/has_spatial_features.rb', line 21 def features_cache_key max_id, count = Feature.where(:spatial_model_type => self).pluck("MAX(id), COUNT(*)").first "#{name}/#{max_id}-#{count}" end |
#intersecting(other, options = {}) ⇒ Object
26 27 28 |
# File 'lib/spatial_features/has_spatial_features.rb', line 26 def intersecting(other, = {}) within_buffer(other, 0, ) end |
#joins_features(table_alias = 'features_for') ⇒ Object
79 80 81 |
# File 'lib/spatial_features/has_spatial_features.rb', line 79 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
74 75 76 77 |
# File 'lib/spatial_features/has_spatial_features.rb', line 74 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
57 58 59 |
# File 'lib/spatial_features/has_spatial_features.rb', line 57 def lines Feature.lines.where(:spatial_model_type => self.class) end |
#points ⇒ Object
61 62 63 |
# File 'lib/spatial_features/has_spatial_features.rb', line 61 def points Feature.points.where(:spatial_model_type => self.class) end |
#polygons ⇒ Object
53 54 55 |
# File 'lib/spatial_features/has_spatial_features.rb', line 53 def polygons Feature.polygons.where(:spatial_model_type => self.class) end |
#within_buffer(other, buffer_in_meters = 0, options = {}) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/spatial_features/has_spatial_features.rb', line 30 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 [:cache] != false # CACHED return all.extending(UncachedRelation) unless other.spatial_cache_for?(self, buffer_in_meters) # Don't use the cache if it doesn't exist 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.geom, features_for_other.geom, ?)', buffer_in_meters) if buffer_in_meters scope = scope.select("MIN(ST_Distance(features_for.geom, features_for_other.geom)) AS distance_in_meters") if [:distance] scope = scope.select("SUM(ST_Area(ST_Intersection(features_for.geom, features_for_other.geom))) AS intersection_area_in_square_meters") if [:intersection_area] end return scope end |