spatial_features 3.3.0 → 3.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -0
- data/app/models/abstract_feature.rb +4 -0
- data/config/initializers/mime_types.rb +0 -4
- data/lib/spatial_features/has_spatial_features/feature_import.rb +4 -4
- data/lib/spatial_features/has_spatial_features.rb +10 -1
- data/lib/spatial_features/importers/base.rb +12 -2
- data/lib/spatial_features/importers/file.rb +19 -17
- data/lib/spatial_features/importers/shapefile.rb +1 -1
- data/lib/spatial_features/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b15396511a7b6b6d17f4a2181793d9b2a35a3a88ba10b49106c9e43cada84b5
|
4
|
+
data.tar.gz: 92c9d1a6b207e1999f63b1e5ab20aec4625b17663e411bcfc7836146c8af4666
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c15ac3afdd9d23f6e12204a775ad2c8c2777a4c65c494f25560c16db189407a513cd694a71b6d289c81fb4b3872a9621d31da31aaa7bec2830bb233a901ad2d4
|
7
|
+
data.tar.gz: c318e7c0897727c41d950451ae7ee65fded8332ded5ec73233660dd8c3285eea571c3160e46eae2b8447131ae8fe0b0559182724719fae3548082ac082e3a3f5
|
data/README.md
CHANGED
@@ -31,6 +31,7 @@ Adds spatial methods to a model.
|
|
31
31
|
feature_type character varying(255),
|
32
32
|
geog geography,
|
33
33
|
geom geometry(Geometry,4326),
|
34
|
+
geom_lowres geometry(Geometry,4326),
|
34
35
|
tilegeom geometry(Geometry,3857),
|
35
36
|
metadata hstore,
|
36
37
|
area double precision,
|
@@ -49,6 +50,7 @@ Adds spatial methods to a model.
|
|
49
50
|
CREATE INDEX index_features_on_feature_type ON features USING btree (feature_type);
|
50
51
|
CREATE INDEX index_features_on_spatial_model_id_and_spatial_model_type ON features USING btree (spatial_model_id, spatial_model_type);
|
51
52
|
CREATE INDEX index_features_on_geom ON features USING gist (geom);
|
53
|
+
CREATE INDEX index_features_on_geom_lowres ON features USING gist (geom_lowres);
|
52
54
|
CREATE INDEX index_features_on_tilegeom ON features USING gist (tilegeom);
|
53
55
|
|
54
56
|
CREATE TABLE spatial_caches (
|
@@ -188,6 +190,16 @@ queries can be optimized. Migrate existing SpatialProximity rows to this new sch
|
|
188
190
|
SpatialProximity.normalize
|
189
191
|
```
|
190
192
|
|
193
|
+
## Upgrading From 3.2/3.3 to 3.4
|
194
|
+
Features now record the source they were imported from in the new `source_identifier` column. This column is indexed and
|
195
|
+
can be used filter features by source.
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
add_column :features, :source_identifier, :string
|
199
|
+
add_index :features, :source_identifier
|
200
|
+
MyModel.update_features!(:force => true) # Force an `update_features!` will populate the source_identifier column.
|
201
|
+
```
|
202
|
+
|
191
203
|
## Testing
|
192
204
|
|
193
205
|
Create a postgres database:
|
@@ -3,7 +3,3 @@ Mime::Type.register "application/vnd.bounds+json", :bounds
|
|
3
3
|
Mime::Type.register "application/vnd.mapbox-vector-tile", :mvt
|
4
4
|
Mime::Type.register "application/vnd.google-earth.kml+xml", :kml
|
5
5
|
Mime::Type.register "application/vnd.google-earth.kmz", :kmz
|
6
|
-
Mime::Type.register "application/zip", :zip
|
7
|
-
Mime::Type.register "application/zip", :piz
|
8
|
-
Mime::Type.register "application/zip", :zap
|
9
|
-
Mime::Type.register "application/zip", :shpz
|
@@ -13,14 +13,14 @@ module SpatialFeatures
|
|
13
13
|
end
|
14
14
|
|
15
15
|
module ClassMethods
|
16
|
-
def update_features!(
|
16
|
+
def update_features!(**options)
|
17
17
|
find_each do |record|
|
18
|
-
record.update_features!(
|
18
|
+
record.update_features!(**options)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def update_features!(skip_invalid: false, allow_blank: false, **options)
|
23
|
+
def update_features!(skip_invalid: false, allow_blank: false, force: false, **options)
|
24
24
|
options = options.reverse_merge(spatial_features_options)
|
25
25
|
tmpdir = options.fetch(:tmpdir) { Dir.mktmpdir("ruby_spatial_features") }
|
26
26
|
|
@@ -28,7 +28,7 @@ module SpatialFeatures
|
|
28
28
|
imports = spatial_feature_imports(options[:import], options[:make_valid], options[:tmpdir])
|
29
29
|
cache_key = Digest::MD5.hexdigest(imports.collect(&:cache_key).join)
|
30
30
|
|
31
|
-
return if features_cache_key_matches?(cache_key)
|
31
|
+
return if !force && features_cache_key_matches?(cache_key)
|
32
32
|
|
33
33
|
run_callbacks :update_features do
|
34
34
|
features = import_features(imports, skip_invalid)
|
@@ -186,7 +186,16 @@ module SpatialFeatures
|
|
186
186
|
end
|
187
187
|
|
188
188
|
def features_cache_key
|
189
|
-
|
189
|
+
fck =
|
190
|
+
if has_spatial_features_hash?
|
191
|
+
features_hash
|
192
|
+
elsif association(:aggregate_feature).loaded?
|
193
|
+
aggregate_feature.cache_key
|
194
|
+
else
|
195
|
+
aggregate_features.cache_key
|
196
|
+
end
|
197
|
+
|
198
|
+
"#{self.class.name}/#{id}-#{fck}"
|
190
199
|
end
|
191
200
|
|
192
201
|
def polygons?
|
@@ -4,12 +4,14 @@ module SpatialFeatures
|
|
4
4
|
module Importers
|
5
5
|
class Base
|
6
6
|
attr_reader :errors
|
7
|
+
attr_accessor :source_identifier # An identifier for the source of the features. Used to differentiate groups of features on the spatial model.
|
7
8
|
|
8
|
-
def initialize(data, make_valid: false, tmpdir: nil)
|
9
|
+
def initialize(data, make_valid: false, tmpdir: nil, source_identifier: nil)
|
9
10
|
@make_valid = make_valid
|
10
11
|
@data = data
|
11
12
|
@errors = []
|
12
13
|
@tmpdir = tmpdir
|
14
|
+
@source_identifier = source_identifier
|
13
15
|
end
|
14
16
|
|
15
17
|
def features
|
@@ -48,7 +50,15 @@ module SpatialFeatures
|
|
48
50
|
|
49
51
|
def build_feature(record)
|
50
52
|
importable_image_paths = record.importable_image_paths if record.respond_to?(:importable_image_paths)
|
51
|
-
Feature.new
|
53
|
+
Feature.new do |feature|
|
54
|
+
feature.name = record.name
|
55
|
+
feature.metadata = record.metadata
|
56
|
+
feature.feature_type = record.feature_type
|
57
|
+
feature.geog = record.geog
|
58
|
+
feature.importable_image_paths = importable_image_paths
|
59
|
+
feature.make_valid = @make_valid
|
60
|
+
feature.source_identifier = source_identifier
|
61
|
+
end
|
52
62
|
end
|
53
63
|
end
|
54
64
|
end
|
@@ -3,23 +3,16 @@ require 'open-uri'
|
|
3
3
|
module SpatialFeatures
|
4
4
|
module Importers
|
5
5
|
class File < SimpleDelegator
|
6
|
-
|
7
|
-
SUPPORTED_SPATIAL_FILE_EXTENSIONS = %w(.zip .zap .piz .shpz .kml .kmz .json .geojson).freeze
|
6
|
+
INVALID_ARCHIVE = "Archive did not contain a .kml, .shp, .json, or .geojson file.".freeze
|
8
7
|
SUPPORTED_FORMATS = "Supported formats are KMZ, KML, zipped ArcGIS shapefiles, ESRI JSON, and GeoJSON.".freeze
|
9
8
|
|
10
|
-
def self.invalid_archive!(filename)
|
11
|
-
filename = ::File.basename(filename.to_s)
|
12
|
-
raise ImportError, "#{filename} did not contain a spatial file. #{SUPPORTED_FORMATS}"
|
13
|
-
end
|
14
|
-
delegate :invalid_archive!, :to => :class
|
15
|
-
|
16
9
|
FILE_PATTERNS = [/\.kml$/, /\.shp$/, /\.json$/, /\.geojson$/]
|
17
10
|
def self.create_all(data, **options)
|
18
11
|
Download.open_each(data, unzip: FILE_PATTERNS, downcase: true, tmpdir: options[:tmpdir]).map do |file|
|
19
12
|
new(data, **options, current_file: file)
|
20
13
|
end
|
21
14
|
rescue Unzip::PathNotFound
|
22
|
-
|
15
|
+
raise ImportError, INVALID_ARCHIVE + " " + SUPPORTED_FORMATS
|
23
16
|
end
|
24
17
|
|
25
18
|
# The File importer may be initialized multiple times by `::create_all` if it
|
@@ -30,30 +23,39 @@ module SpatialFeatures
|
|
30
23
|
# If no `current_file` is passed then we just take the first valid file that we find.
|
31
24
|
def initialize(data, current_file: nil, **options)
|
32
25
|
begin
|
33
|
-
current_file
|
26
|
+
@current_file = current_file || Download.open_each(data, unzip: FILE_PATTERNS, downcase: true, tmpdir: options[:tmpdir]).first
|
34
27
|
rescue Unzip::PathNotFound
|
35
|
-
|
28
|
+
raise ImportError, INVALID_ARCHIVE
|
36
29
|
end
|
37
30
|
|
38
|
-
|
31
|
+
case ::File.extname(data).downcase
|
32
|
+
when '.kmz' # KMZ always has a single kml in it, so no need to show mention it
|
33
|
+
options[:source_identifier] = ::File.basename(data)
|
34
|
+
else
|
35
|
+
options[:source_identifier] = [::File.basename(data), ::File.basename(@current_file.path)].uniq.join('/')
|
36
|
+
end
|
39
37
|
|
40
38
|
case ::File.extname(filename)
|
41
39
|
when '.kml'
|
42
|
-
__setobj__(KMLFile.new(current_file, **options))
|
40
|
+
__setobj__(KMLFile.new(@current_file, **options))
|
43
41
|
when '.shp'
|
44
|
-
__setobj__(Shapefile.new(current_file, **options))
|
42
|
+
__setobj__(Shapefile.new(@current_file, **options))
|
45
43
|
when '.json', '.geojson'
|
46
|
-
__setobj__(ESRIGeoJSON.new(current_file.path, **options))
|
44
|
+
__setobj__(ESRIGeoJSON.new(@current_file.path, **options))
|
47
45
|
else
|
48
|
-
import_error
|
46
|
+
import_error
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
52
50
|
private
|
53
51
|
|
54
|
-
def import_error!
|
52
|
+
def import_error!
|
55
53
|
raise ImportError, "Could not import #{filename}. " + SUPPORTED_FORMATS
|
56
54
|
end
|
55
|
+
|
56
|
+
def filename
|
57
|
+
@filename ||= @current_file.path.downcase
|
58
|
+
end
|
57
59
|
end
|
58
60
|
end
|
59
61
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spatial_features
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Wallace
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-10-
|
12
|
+
date: 2023-10-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|