aqila-mapas 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +1223 -0
- data/.travis.yml +5 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +49 -0
- data/README.md +31 -0
- data/Rakefile +8 -0
- data/aqila-mapas.gemspec +36 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/aqila/mapas/railtie.rb +13 -0
- data/lib/aqila/mapas/version.rb +7 -0
- data/lib/aqila/mapas.rb +57 -0
- data/lib/map/download_tiles_service.rb +74 -0
- data/lib/map/file_import_basic.rb +30 -0
- data/lib/map/float.rb +13 -0
- data/lib/map/gdal/base.rb +66 -0
- data/lib/map/gdal/colorize_service.rb +82 -0
- data/lib/map/gdal/contrast_stretch_service.rb +26 -0
- data/lib/map/gdal/crop_service.rb +36 -0
- data/lib/map/gdal/gdal_info_service.rb +32 -0
- data/lib/map/gdal/grid_service.rb +36 -0
- data/lib/map/gdal/merge_service.rb +22 -0
- data/lib/map/gdal/ndvi_service.rb +32 -0
- data/lib/map/gdal/ogr2ogr_service.rb +23 -0
- data/lib/map/gdal/ogri_info_service.rb +35 -0
- data/lib/map/gdal/polygonize_service.rb +36 -0
- data/lib/map/gdal/raster_service.rb +36 -0
- data/lib/map/gdal/rgb_service.rb +27 -0
- data/lib/map/gdal/table_colors.txt +52 -0
- data/lib/map/gdal/tiles_service.rb +21 -0
- data/lib/map/gdal/translate_service.rb +37 -0
- data/lib/map/gdal/warp_service.rb +22 -0
- data/lib/map/gleba_tiles_service.rb +29 -0
- data/lib/map/gpx_service.rb +34 -0
- data/lib/map/kml_creator_line_service.rb +31 -0
- data/lib/map/kml_creator_service.rb +31 -0
- data/lib/map/kml_edit_service.rb +122 -0
- data/lib/map/kml_offset_service.rb +59 -0
- data/lib/map/kml_service.rb +35 -0
- data/lib/map/lat_lon_service.rb +93 -0
- data/lib/map/polygon_service.rb +100 -0
- data/lib/map/rgeo_service.rb +42 -0
- data/lib/map/shape_to_tif_service.rb +89 -0
- data/lib/map/tile_service.rb +22 -0
- data/lib/map/tiles_base.rb +11 -0
- data/lib/map/tracking_cleaner_service.rb +78 -0
- data/lib/satellite/imagery_proccessor.rb +70 -0
- data/lib/satellite/landsat8/coordinate_converter_service.rb +40 -0
- data/lib/satellite/landsat8/imagery_service.rb +113 -0
- data/lib/satellite/sentinel2/coordinate_converter_service.rb +90 -0
- data/lib/satellite/sentinel2/imagery_service.rb +144 -0
- metadata +137 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open-uri'
|
4
|
+
|
5
|
+
module Satellite
|
6
|
+
module Sentinel2
|
7
|
+
class CoordinateConverterService
|
8
|
+
# Arquivo baixado em https://sentinel.esa.int/web/sentinel/missions/sentinel-2/data-products
|
9
|
+
KML_FILE = 'S2A_OPER_GIP_TILPAR_MPC__20151209T095117_V20150622T000000_21000101T000000_B00.kml'
|
10
|
+
KML_FILE_URL = "https://sentinel.esa.int/documents/247904/1955685/#{KML_FILE}"
|
11
|
+
FILE_SIZE = 108817408
|
12
|
+
|
13
|
+
attr_accessor :lat, :lon
|
14
|
+
|
15
|
+
def initialize(lat, lon)
|
16
|
+
self.lat = lat
|
17
|
+
self.lon = lon
|
18
|
+
end
|
19
|
+
|
20
|
+
def convert
|
21
|
+
cache_key = "Sentinel2KML-#{FILE_SIZE}"
|
22
|
+
cached = Redis.current.get(cache_key)
|
23
|
+
if cached
|
24
|
+
cached = JSON.parse(cached)
|
25
|
+
else
|
26
|
+
cached = parsed_kml
|
27
|
+
Redis.current.set(cache_key, cached.to_json, ex: 86400)
|
28
|
+
end
|
29
|
+
|
30
|
+
found = cached.find do |polygon|
|
31
|
+
Map::PolygonService.new.inside_polygons?({latitude: lat, longitude: lon}, polygon['coordinates'])
|
32
|
+
end
|
33
|
+
|
34
|
+
return unless found
|
35
|
+
|
36
|
+
creator = Map::KmlCreatorService.new
|
37
|
+
found['coordinates'].each { |c| creator.add_polygon(c) }
|
38
|
+
kml_service = Map::KmlService.new(creator.to_xml)
|
39
|
+
bounds = {
|
40
|
+
point_more_south_west: kml_service.point_more_south_west,
|
41
|
+
point_more_north_east: kml_service.point_more_north_east
|
42
|
+
}
|
43
|
+
|
44
|
+
{
|
45
|
+
name: found['name'],
|
46
|
+
bounds: bounds
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def parsed_kml
|
53
|
+
FileUtils.mkdir_p(File.dirname(kml_file_path))
|
54
|
+
|
55
|
+
download_kml_file! unless kml_file_exists? && kml_file_is_valid?
|
56
|
+
|
57
|
+
File.open(kml_file_path) do |file|
|
58
|
+
Nokogiri::XML::Reader.from_io(file).map do |node|
|
59
|
+
next unless node.name == 'Placemark'
|
60
|
+
|
61
|
+
root = Nokogiri::XML(node.outer_xml).root
|
62
|
+
coordinates = Map::KmlService.new(root).coordinates
|
63
|
+
{
|
64
|
+
'name' => root&.at('name')&.text,
|
65
|
+
'coordinates' => coordinates
|
66
|
+
}
|
67
|
+
end.compact
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def download_kml_file!
|
72
|
+
open(kml_file_path, 'wb') do |file|
|
73
|
+
file << URI.open(KML_FILE_URL).read
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def kml_file_exists?
|
78
|
+
File.exist?(kml_file_path)
|
79
|
+
end
|
80
|
+
|
81
|
+
def kml_file_is_valid?
|
82
|
+
File.size(kml_file_path) == FILE_SIZE
|
83
|
+
end
|
84
|
+
|
85
|
+
def kml_file_path
|
86
|
+
File.join(Dir.pwd, 'public', 'system', 'data', KML_FILE)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Satellite Sentinel2
|
4
|
+
# 10m de resolução
|
5
|
+
# Banda 2 = Azul
|
6
|
+
# Banda 3 = Verde
|
7
|
+
# Banda 4 = Vermelho
|
8
|
+
# Banda 8 = Infravermelho próximo
|
9
|
+
module Satellite
|
10
|
+
module Sentinel2
|
11
|
+
class ImageryService
|
12
|
+
# Informações sobre --region eu-central-1 --request-payer requester:
|
13
|
+
# https://forum.sentinel-hub.com/t/changes-of-the-access-rights-to-l1c-bucket-at-aws-public-datasets-requester-pays/172
|
14
|
+
AWS_URL = '--region eu-central-1 --request-payer requester s3://sentinel-s2-l1c/tiles'
|
15
|
+
|
16
|
+
attr_accessor :scene, :quantity
|
17
|
+
|
18
|
+
# $scene = '12ABC' String(5)
|
19
|
+
def initialize(scene, quantity = 2)
|
20
|
+
self.scene = "#{scene[0..1]}/#{scene[2]}/#{scene[3..4]}"
|
21
|
+
self.quantity = quantity
|
22
|
+
end
|
23
|
+
|
24
|
+
def download_and_proccess
|
25
|
+
Rails.logger.info "[Sentinel2 | #{scene}] Listando últimos #{quantity} arquivos..."
|
26
|
+
files = last_scene_dates
|
27
|
+
|
28
|
+
Rails.logger.info "[Sentinel2 | #{scene}] Checando arquivos que precisam ser baixados..."
|
29
|
+
files.reject!{ |scene_date| scene_already_proccessed?(scene_date) }
|
30
|
+
|
31
|
+
Rails.logger.info "[Sentinel2 | #{scene}] Baixando #{files.length} cenas..."
|
32
|
+
files.each_with_index do |scene_date, index|
|
33
|
+
Rails.logger.info "[Sentinel2 | #{scene}] Fazendo download da cena do dia #{scene_date}..."
|
34
|
+
useful_files(scene_date).map do |useful_file|
|
35
|
+
Thread.new {
|
36
|
+
Rails.logger.info "[Sentinel2 | #{scene}] Fazendo download do arquivo #{useful_file}..."
|
37
|
+
`aws s3 cp #{AWS_URL}/#{scene}/#{scene_date}/0/#{useful_file} "#{output_path}/#{scene}/#{scene_date}/#{useful_file}"`
|
38
|
+
raise 'Error to execute aws s3 cp' unless $?.success?
|
39
|
+
}
|
40
|
+
end.map(&:join)
|
41
|
+
|
42
|
+
Rails.logger.info "[Sentinel2 | #{scene}] Processando arquivos #{index.next}/#{files.length}."
|
43
|
+
Satellite::ImageryProccessor.new(band_object(scene_date)).proccess
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def last_scene_dates
|
48
|
+
return @last_scene_dates if @last_scene_dates.present?
|
49
|
+
|
50
|
+
@last_scene_dates = []
|
51
|
+
|
52
|
+
scene_years.sort.reverse.each do |year|
|
53
|
+
break if @last_scene_dates.size == quantity
|
54
|
+
scene_months(year).sort.reverse.each do |month|
|
55
|
+
break if @last_scene_dates.size == quantity
|
56
|
+
scene_days(year, month).sort.reverse.each do |day|
|
57
|
+
break if @last_scene_dates.size == quantity
|
58
|
+
@last_scene_dates << "#{year}/#{month}/#{day}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
@last_scene_dates
|
64
|
+
end
|
65
|
+
|
66
|
+
def string_as_integer
|
67
|
+
->(string) { string[/(\d+)/, 1].to_i }
|
68
|
+
end
|
69
|
+
|
70
|
+
def scene_years
|
71
|
+
return @scene_years if @scene_years.present?
|
72
|
+
|
73
|
+
years_list = `aws s3 ls #{AWS_URL}/#{scene}/`
|
74
|
+
raise 'Falha ao executar comando para adquirir os anos da cena' unless $?.success?
|
75
|
+
@scene_years = years_list.split("\n").map(&string_as_integer)
|
76
|
+
end
|
77
|
+
|
78
|
+
def scene_months(year)
|
79
|
+
months_list = `aws s3 ls #{AWS_URL}/#{scene}/#{year}/`
|
80
|
+
raise 'Falha ao executar comando para adquirir o mês da última cena' unless $?.success?
|
81
|
+
|
82
|
+
months_list.split("\n").map(&string_as_integer)
|
83
|
+
end
|
84
|
+
|
85
|
+
def scene_days(year, month)
|
86
|
+
days_list = `aws s3 ls #{AWS_URL}/#{scene}/#{year}/#{month}/`
|
87
|
+
raise 'Falha ao executar comando para adquirir o dia da última cena' unless $?.success?
|
88
|
+
|
89
|
+
days_list.split("\n").map(&string_as_integer)
|
90
|
+
end
|
91
|
+
|
92
|
+
def useful_files(scene_date)
|
93
|
+
# O parâmetro 0 no fim da string é por que caso o satélite tire mais de uma foto no mesmo dia
|
94
|
+
# estas serão armazenadas em /1, /2, etc... porém isso só ocorre em latitudes do norte.
|
95
|
+
all_files_from_last_scene = `aws s3 ls #{AWS_URL}/#{scene}/#{scene_date}/0/`
|
96
|
+
raise 'Falha ao executar comando para adquirir a lista de arquivos' unless $?.success?
|
97
|
+
|
98
|
+
@useful_files = all_files_from_last_scene.split("\n").inject([]) do |useful_files, current_file|
|
99
|
+
filtered_file = current_file[/.*(B0[2-4].jp2|B08.jp2|preview.jpg)$/, 1]
|
100
|
+
useful_files << filtered_file if filtered_file.present?
|
101
|
+
useful_files
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def output_path
|
106
|
+
return @path if @path.present?
|
107
|
+
|
108
|
+
@path = File.join(Dir.pwd, 'public', 'system', 'data', 'imagens', 'sentinel2')
|
109
|
+
FileUtils.mkdir_p(@path)
|
110
|
+
@path
|
111
|
+
end
|
112
|
+
|
113
|
+
def scene_already_proccessed?(scene_date)
|
114
|
+
Scene
|
115
|
+
.sentinel2
|
116
|
+
.by_date(scene_date.to_date)
|
117
|
+
.by_scene(scene.delete('/'))
|
118
|
+
.exists?
|
119
|
+
end
|
120
|
+
|
121
|
+
def info_object(scene_date)
|
122
|
+
{
|
123
|
+
date: scene_date.to_date,
|
124
|
+
cloud_cover: nil,
|
125
|
+
scene: scene.delete('/'),
|
126
|
+
source: :sentinel2,
|
127
|
+
base_path: output_path,
|
128
|
+
files_path: "#{output_path}/#{scene}/#{scene_date}"
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
def band_object(scene_date)
|
133
|
+
{
|
134
|
+
blue: "#{output_path}/#{scene}/#{scene_date}/B02.jp2",
|
135
|
+
green: "#{output_path}/#{scene}/#{scene_date}/B03.jp2",
|
136
|
+
red: "#{output_path}/#{scene}/#{scene_date}/B04.jp2",
|
137
|
+
near_infrared: "#{output_path}/#{scene}/#{scene_date}/B08.jp2",
|
138
|
+
large_thumb: "#{output_path}/#{scene}/#{scene_date}/preview.jpg",
|
139
|
+
info: info_object(scene_date)
|
140
|
+
}
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aqila-mapas
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- lucasferronato
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-02-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
description: Documentar
|
56
|
+
email:
|
57
|
+
- lucas_ferronato@hotmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- ".rspec"
|
64
|
+
- ".rubocop.yml"
|
65
|
+
- ".travis.yml"
|
66
|
+
- Gemfile
|
67
|
+
- Gemfile.lock
|
68
|
+
- README.md
|
69
|
+
- Rakefile
|
70
|
+
- aqila-mapas.gemspec
|
71
|
+
- bin/console
|
72
|
+
- bin/setup
|
73
|
+
- lib/aqila/mapas.rb
|
74
|
+
- lib/aqila/mapas/railtie.rb
|
75
|
+
- lib/aqila/mapas/version.rb
|
76
|
+
- lib/map/download_tiles_service.rb
|
77
|
+
- lib/map/file_import_basic.rb
|
78
|
+
- lib/map/float.rb
|
79
|
+
- lib/map/gdal/base.rb
|
80
|
+
- lib/map/gdal/colorize_service.rb
|
81
|
+
- lib/map/gdal/contrast_stretch_service.rb
|
82
|
+
- lib/map/gdal/crop_service.rb
|
83
|
+
- lib/map/gdal/gdal_info_service.rb
|
84
|
+
- lib/map/gdal/grid_service.rb
|
85
|
+
- lib/map/gdal/merge_service.rb
|
86
|
+
- lib/map/gdal/ndvi_service.rb
|
87
|
+
- lib/map/gdal/ogr2ogr_service.rb
|
88
|
+
- lib/map/gdal/ogri_info_service.rb
|
89
|
+
- lib/map/gdal/polygonize_service.rb
|
90
|
+
- lib/map/gdal/raster_service.rb
|
91
|
+
- lib/map/gdal/rgb_service.rb
|
92
|
+
- lib/map/gdal/table_colors.txt
|
93
|
+
- lib/map/gdal/tiles_service.rb
|
94
|
+
- lib/map/gdal/translate_service.rb
|
95
|
+
- lib/map/gdal/warp_service.rb
|
96
|
+
- lib/map/gleba_tiles_service.rb
|
97
|
+
- lib/map/gpx_service.rb
|
98
|
+
- lib/map/kml_creator_line_service.rb
|
99
|
+
- lib/map/kml_creator_service.rb
|
100
|
+
- lib/map/kml_edit_service.rb
|
101
|
+
- lib/map/kml_offset_service.rb
|
102
|
+
- lib/map/kml_service.rb
|
103
|
+
- lib/map/lat_lon_service.rb
|
104
|
+
- lib/map/polygon_service.rb
|
105
|
+
- lib/map/rgeo_service.rb
|
106
|
+
- lib/map/shape_to_tif_service.rb
|
107
|
+
- lib/map/tile_service.rb
|
108
|
+
- lib/map/tiles_base.rb
|
109
|
+
- lib/map/tracking_cleaner_service.rb
|
110
|
+
- lib/satellite/imagery_proccessor.rb
|
111
|
+
- lib/satellite/landsat8/coordinate_converter_service.rb
|
112
|
+
- lib/satellite/landsat8/imagery_service.rb
|
113
|
+
- lib/satellite/sentinel2/coordinate_converter_service.rb
|
114
|
+
- lib/satellite/sentinel2/imagery_service.rb
|
115
|
+
homepage: https://github.com/mateusnava/aqila-mapas
|
116
|
+
licenses: []
|
117
|
+
metadata: {}
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
requirements: []
|
133
|
+
rubygems_version: 3.0.9
|
134
|
+
signing_key:
|
135
|
+
specification_version: 4
|
136
|
+
summary: Documentar
|
137
|
+
test_files: []
|