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
64 65 66 67 68 69 70 71 |
# File 'lib/spatial_features/has_spatial_features.rb', line 64 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
78 79 80 |
# File 'lib/spatial_features/has_spatial_features.rb', line 78 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
73 74 75 76 |
# File 'lib/spatial_features/has_spatial_features.rb', line 73 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
56 57 58 |
# File 'lib/spatial_features/has_spatial_features.rb', line 56 def lines Feature.lines.where(:spatial_model_type => self.class) end |
#points ⇒ Object
60 61 62 |
# File 'lib/spatial_features/has_spatial_features.rb', line 60 def points Feature.points.where(:spatial_model_type => self.class) end |
#polygons ⇒ Object
52 53 54 |
# File 'lib/spatial_features/has_spatial_features.rb', line 52 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 49 50 |
# 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 [: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 |