nswtopo 2.0.0.pre.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +674 -0
  3. data/bin/nswtopo +430 -0
  4. data/docs/README.md +78 -0
  5. data/docs/add.md +49 -0
  6. data/docs/config.md +24 -0
  7. data/docs/contours.md +37 -0
  8. data/docs/controls.md +9 -0
  9. data/docs/declination.md +15 -0
  10. data/docs/delete.md +15 -0
  11. data/docs/grid.md +5 -0
  12. data/docs/info.md +5 -0
  13. data/docs/init.md +38 -0
  14. data/docs/layers.md +11 -0
  15. data/docs/overlay.md +37 -0
  16. data/docs/relief.md +22 -0
  17. data/docs/render.md +43 -0
  18. data/docs/spot-heights.md +23 -0
  19. data/lib/nswtopo/archive.rb +93 -0
  20. data/lib/nswtopo/avl_tree.rb +128 -0
  21. data/lib/nswtopo/config.rb +73 -0
  22. data/lib/nswtopo/dither.rb +31 -0
  23. data/lib/nswtopo/font/chrome.rb +59 -0
  24. data/lib/nswtopo/font/generic.rb +25 -0
  25. data/lib/nswtopo/font.rb +43 -0
  26. data/lib/nswtopo/formats/kmz.rb +149 -0
  27. data/lib/nswtopo/formats/mbtiles.rb +64 -0
  28. data/lib/nswtopo/formats/pdf.rb +31 -0
  29. data/lib/nswtopo/formats/svg.rb +69 -0
  30. data/lib/nswtopo/formats/svgz.rb +13 -0
  31. data/lib/nswtopo/formats/zip.rb +40 -0
  32. data/lib/nswtopo/formats.rb +76 -0
  33. data/lib/nswtopo/geometry/overlap.rb +78 -0
  34. data/lib/nswtopo/geometry/r_tree.rb +47 -0
  35. data/lib/nswtopo/geometry/segment.rb +27 -0
  36. data/lib/nswtopo/geometry/straight_skeleton/collapse.rb +21 -0
  37. data/lib/nswtopo/geometry/straight_skeleton/interior_node.rb +17 -0
  38. data/lib/nswtopo/geometry/straight_skeleton/node.rb +50 -0
  39. data/lib/nswtopo/geometry/straight_skeleton/nodes.rb +295 -0
  40. data/lib/nswtopo/geometry/straight_skeleton/split.rb +33 -0
  41. data/lib/nswtopo/geometry/straight_skeleton/vertex.rb +9 -0
  42. data/lib/nswtopo/geometry/straight_skeleton.rb +6 -0
  43. data/lib/nswtopo/geometry/vector.rb +91 -0
  44. data/lib/nswtopo/geometry/vector_sequence.rb +179 -0
  45. data/lib/nswtopo/geometry.rb +8 -0
  46. data/lib/nswtopo/gis/arcgis_server/connection.rb +52 -0
  47. data/lib/nswtopo/gis/arcgis_server.rb +155 -0
  48. data/lib/nswtopo/gis/dem.rb +70 -0
  49. data/lib/nswtopo/gis/esri_hdr.rb +77 -0
  50. data/lib/nswtopo/gis/gdal_glob.rb +41 -0
  51. data/lib/nswtopo/gis/geojson/collection.rb +94 -0
  52. data/lib/nswtopo/gis/geojson/line_string.rb +11 -0
  53. data/lib/nswtopo/gis/geojson/multi_line_string.rb +63 -0
  54. data/lib/nswtopo/gis/geojson/multi_point.rb +12 -0
  55. data/lib/nswtopo/gis/geojson/multi_polygon.rb +167 -0
  56. data/lib/nswtopo/gis/geojson/point.rb +9 -0
  57. data/lib/nswtopo/gis/geojson/polygon.rb +11 -0
  58. data/lib/nswtopo/gis/geojson.rb +89 -0
  59. data/lib/nswtopo/gis/gps/gpx.rb +22 -0
  60. data/lib/nswtopo/gis/gps/kml.rb +66 -0
  61. data/lib/nswtopo/gis/gps.rb +20 -0
  62. data/lib/nswtopo/gis/projection.rb +56 -0
  63. data/lib/nswtopo/gis/shapefile.rb +24 -0
  64. data/lib/nswtopo/gis/world_file.rb +19 -0
  65. data/lib/nswtopo/gis.rb +9 -0
  66. data/lib/nswtopo/help_formatter.rb +59 -0
  67. data/lib/nswtopo/helpers/array.rb +30 -0
  68. data/lib/nswtopo/helpers/colour.rb +176 -0
  69. data/lib/nswtopo/helpers/concurrently.rb +27 -0
  70. data/lib/nswtopo/helpers/dir.rb +7 -0
  71. data/lib/nswtopo/helpers/hash.rb +15 -0
  72. data/lib/nswtopo/helpers/tar_writer.rb +11 -0
  73. data/lib/nswtopo/helpers.rb +6 -0
  74. data/lib/nswtopo/layer/arcgis_raster.rb +73 -0
  75. data/lib/nswtopo/layer/contour.rb +233 -0
  76. data/lib/nswtopo/layer/control.rb +94 -0
  77. data/lib/nswtopo/layer/declination.rb +53 -0
  78. data/lib/nswtopo/layer/feature.rb +87 -0
  79. data/lib/nswtopo/layer/grid.rb +120 -0
  80. data/lib/nswtopo/layer/import.rb +25 -0
  81. data/lib/nswtopo/layer/labels/fence.rb +20 -0
  82. data/lib/nswtopo/layer/labels.rb +630 -0
  83. data/lib/nswtopo/layer/overlay.rb +53 -0
  84. data/lib/nswtopo/layer/raster.rb +63 -0
  85. data/lib/nswtopo/layer/relief.rb +143 -0
  86. data/lib/nswtopo/layer/spot.rb +171 -0
  87. data/lib/nswtopo/layer/vector.rb +263 -0
  88. data/lib/nswtopo/layer/vegetation.rb +73 -0
  89. data/lib/nswtopo/layer.rb +78 -0
  90. data/lib/nswtopo/log.rb +28 -0
  91. data/lib/nswtopo/map.rb +296 -0
  92. data/lib/nswtopo/os.rb +75 -0
  93. data/lib/nswtopo/safely.rb +13 -0
  94. data/lib/nswtopo/version.rb +4 -0
  95. data/lib/nswtopo/zip.rb +15 -0
  96. data/lib/nswtopo.rb +249 -0
  97. metadata +142 -0
data/lib/nswtopo.rb ADDED
@@ -0,0 +1,249 @@
1
+ require 'date'
2
+ require 'open3'
3
+ require 'uri'
4
+ require 'net/http'
5
+ require 'rexml/document'
6
+ require 'rexml/formatters/pretty'
7
+ require 'tmpdir'
8
+ require 'yaml'
9
+ require 'fileutils'
10
+ require 'pathname'
11
+ require 'json'
12
+ require 'base64'
13
+ require 'set'
14
+ require 'etc'
15
+ require 'timeout'
16
+ require 'ostruct'
17
+ require 'forwardable'
18
+ require 'rubygems/package'
19
+ require 'zlib'
20
+ begin
21
+ require 'pty'
22
+ require 'expect'
23
+ rescue LoadError
24
+ end
25
+
26
+ require_relative 'nswtopo/helpers'
27
+ require_relative 'nswtopo/avl_tree'
28
+ require_relative 'nswtopo/geometry'
29
+ require_relative 'nswtopo/log'
30
+ require_relative 'nswtopo/safely'
31
+ require_relative 'nswtopo/os'
32
+ require_relative 'nswtopo/dither'
33
+ require_relative 'nswtopo/zip'
34
+ require_relative 'nswtopo/font'
35
+ require_relative 'nswtopo/archive'
36
+ require_relative 'nswtopo/gis'
37
+ require_relative 'nswtopo/formats'
38
+ require_relative 'nswtopo/map'
39
+ require_relative 'nswtopo/layer'
40
+ require_relative 'nswtopo/version'
41
+ require_relative 'nswtopo/config'
42
+
43
+ module NSWTopo
44
+ PartialFailureError = Class.new RuntimeError
45
+ extend self, Log
46
+
47
+ def init(archive, options)
48
+ puts Map.init(archive, options)
49
+ end
50
+
51
+ def layer_dirs
52
+ @layer_dirs ||= Array(Config["layer-dir"]).map(&Pathname.method(:new)) << Pathname.pwd
53
+ end
54
+
55
+ def info(archive, options)
56
+ puts Map.load(archive).info(options)
57
+ end
58
+
59
+ def add(archive, *layers, options)
60
+ create_options = {
61
+ after: Layer.sanitise(options.delete :after),
62
+ before: Layer.sanitise(options.delete :before),
63
+ replace: Layer.sanitise(options.delete :replace),
64
+ overwrite: options.delete(:overwrite)
65
+ }
66
+ map = Map.load archive
67
+
68
+ Enumerator.new do |yielder|
69
+ while layers.any?
70
+ layer, basedir = layers.shift
71
+ path = Pathname(layer).expand_path(*basedir)
72
+ case layer
73
+ when /^controls\.(gpx|kml)$/i
74
+ yielder << [path.basename(path.extname).to_s, "type" => "Control", "path" => path]
75
+ when /\.(gpx|kml)$/i
76
+ yielder << [path.basename(path.extname).to_s, "type" => "Overlay", "path" => path]
77
+ when /\.(tiff?|png|jpg)$/i
78
+ yielder << [path.basename(path.extname).to_s, "type" => "Import", "path" => path]
79
+ when "contours"
80
+ yielder << [layer, "type" => "Contour"]
81
+ when "spot-heights"
82
+ yielder << [layer, "type" => "Spot"]
83
+ when "relief"
84
+ yielder << [layer, "type" => "Relief"]
85
+ when "grid"
86
+ yielder << [layer, "type" => "Grid"]
87
+ when "declination"
88
+ yielder << [layer, "type" => "Declination"]
89
+ when "controls"
90
+ yielder << [layer, "type" => "Control"]
91
+ when /\.yml$/i
92
+ basedir ||= path.parent
93
+ raise "couldn't find '#{layer}'" unless path.file?
94
+ case contents = YAML.load(path.read)
95
+ when Array
96
+ contents.reverse.map do |item|
97
+ Pathname(item.to_s)
98
+ end.each do |relative_path|
99
+ raise "#{relative_path} is not a relative path" unless relative_path.relative?
100
+ layers.prepend [Pathname(relative_path).expand_path(path.parent).relative_path_from(basedir).to_s, basedir]
101
+ end
102
+ when Hash
103
+ name = path.sub_ext("").relative_path_from(basedir).descend.map(&:basename).join(?.)
104
+ yielder << [name, contents.merge("source" => path)]
105
+ else
106
+ raise "couldn't parse #{path}"
107
+ end
108
+ else
109
+ path = Pathname("#{layer}.yml")
110
+ raise "#{layer} is not a relative path" unless path.relative?
111
+ basedir ||= layer_dirs.find do |root|
112
+ path.expand_path(root).file?
113
+ end
114
+ layers.prepend [path.to_s, basedir]
115
+ end
116
+ end
117
+ rescue YAML::Exception
118
+ raise "couldn't parse #{path}"
119
+ end.map do |name, params|
120
+ params.merge! options.transform_keys(&:to_s)
121
+ params.merge! Config[name] if Config[name]
122
+ Layer.new(name, map, params)
123
+ end.tap do |layers|
124
+ raise OptionParser::MissingArgument, "no layers specified" unless layers.any?
125
+ unless layers.one?
126
+ raise OptionParser::InvalidArgument, "can't specify resolution when adding multiple layers" if options[:resolution]
127
+ raise OptionParser::InvalidArgument, "can't specify data path when adding multiple layers" if options[:path]
128
+ end
129
+ map.add *layers, create_options
130
+ end
131
+ end
132
+
133
+ def contours(archive, dem_path, options)
134
+ add archive, "contours", options.merge(path: Pathname(dem_path))
135
+ end
136
+
137
+ def spot_heights(archive, dem_path, options)
138
+ add archive, "spot-heights", options.merge(path: Pathname(dem_path))
139
+ end
140
+
141
+ def relief(archive, dem_path, options)
142
+ add archive, "relief", options.merge(path: Pathname(dem_path))
143
+ end
144
+
145
+ def grid(archive, options)
146
+ add archive, "grid", options
147
+ end
148
+
149
+ def declination(archive, options)
150
+ add archive, "declination", options
151
+ end
152
+
153
+ def controls(archive, gps_path, options)
154
+ add archive, "controls", options.merge(path: Pathname(gps_path))
155
+ end
156
+
157
+ def overlay(archive, gps_path, options)
158
+ raise OptionParser::InvalidArgument, gps_path unless gps_path =~ /\.(gpx|kml)$/i
159
+ add archive, gps_path, options.merge(path: Pathname(gps_path))
160
+ end
161
+
162
+ def delete(archive, *names, options)
163
+ map = Map.load archive
164
+ names.map do |name|
165
+ Layer.sanitise name
166
+ end.uniq.map do |name|
167
+ name[?*] ? %r[^#{name.gsub(?., '\.').gsub(?*, '.*')}$] : name
168
+ end.tap do |names|
169
+ map.delete *names
170
+ end
171
+ end
172
+
173
+ def render(archive, *formats, options)
174
+ overwrite = options.delete :overwrite
175
+ formats << "svg" if formats.empty?
176
+ formats.map do |format|
177
+ Pathname(Formats === format ? "#{archive.basename}.#{format}" : format)
178
+ end.uniq.each do |path|
179
+ format = path.extname.delete_prefix(?.)
180
+ raise "unrecognised format: #{path}" if format.empty?
181
+ raise "unrecognised format: #{format}" unless Formats === format
182
+ raise "file already exists: #{path}" if path.exist? && !overwrite
183
+ raise "non-existent directory: #{path.parent}" unless path.parent.directory?
184
+ end.tap do |paths|
185
+ Map.load(archive).render *paths, options
186
+ end
187
+ end
188
+
189
+ def layers(state: nil, indent: "")
190
+ layer_dirs.grep_v(Pathname.pwd).flat_map do |directory|
191
+ Array(state).inject(directory, &:/).glob("*")
192
+ end.sort.each do |path|
193
+ case
194
+ when path.directory?
195
+ next if path.glob("**/*.yml").none?
196
+ puts [indent, path.basename.sub_ext("")].join
197
+ layers state: [*state, path.basename], indent: " " + indent
198
+ when path.sub_ext("").directory?
199
+ when path.extname == ".yml"
200
+ puts [indent, path.basename.sub_ext("")].join
201
+ end
202
+ end.tap do |paths|
203
+ log_warn "no layers installed" if paths.none?
204
+ end
205
+ end
206
+
207
+ def config(layer = nil, **options)
208
+ chrome, firefox, path, resolution, layer_dir, labelling, delete = options.values_at :chrome, :firefox, :path, :resolution, :"layer-dir", :labelling, :delete
209
+ raise "not a directory: %s" % layer_dir if layer_dir && !layer_dir.directory?
210
+ raise "chrome path is not an executable" if chrome && !chrome.executable?
211
+ raise "firefox path is not an executable" if firefox && !firefox.executable?
212
+ Config.store("chrome", chrome.to_s) if chrome
213
+ Config.store("firefox", firefox.to_s) if firefox
214
+ Config.store("labelling", labelling) unless labelling.nil?
215
+ Config.store("layer-dir", layer_dir.to_s) if layer_dir
216
+
217
+ layer = Layer.sanitise layer
218
+ case
219
+ when !layer
220
+ raise OptionParser::InvalidArgument, "no layer name specified for path" if path
221
+ raise OptionParser::InvalidArgument, "no layer name specified for resolution" if resolution
222
+ when path || resolution
223
+ Config.store(layer, "path", path.to_s) if path
224
+ Config.store(layer, "resolution", resolution) if resolution
225
+ end
226
+ Config.delete(*layer, delete) if delete
227
+
228
+ if options.empty?
229
+ puts Config.to_str.each_line.drop(1)
230
+ log_neutral "no configuration yet" if Config.empty?
231
+ else
232
+ Config.save
233
+ log_success "configuration updated"
234
+ end
235
+ end
236
+
237
+ def with_browser
238
+ browser_name, browser_path = Config.slice("chrome", "firefox").first
239
+ raise "please configure a path for google chrome" unless browser_name
240
+ yield browser_name, Pathname.new(browser_path)
241
+ rescue Errno::ENOENT
242
+ raise "invalid %s path: %s" % [browser_name, browser_path]
243
+ end
244
+ end
245
+
246
+ begin
247
+ require 'nswtopo/layers'
248
+ rescue LoadError
249
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nswtopo
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0.pre.beta1
5
+ platform: ruby
6
+ authors:
7
+ - Matthew Hollingworth
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-02-13 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ executables:
16
+ - nswtopo
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - COPYING
21
+ - bin/nswtopo
22
+ - docs/README.md
23
+ - docs/add.md
24
+ - docs/config.md
25
+ - docs/contours.md
26
+ - docs/controls.md
27
+ - docs/declination.md
28
+ - docs/delete.md
29
+ - docs/grid.md
30
+ - docs/info.md
31
+ - docs/init.md
32
+ - docs/layers.md
33
+ - docs/overlay.md
34
+ - docs/relief.md
35
+ - docs/render.md
36
+ - docs/spot-heights.md
37
+ - lib/nswtopo.rb
38
+ - lib/nswtopo/archive.rb
39
+ - lib/nswtopo/avl_tree.rb
40
+ - lib/nswtopo/config.rb
41
+ - lib/nswtopo/dither.rb
42
+ - lib/nswtopo/font.rb
43
+ - lib/nswtopo/font/chrome.rb
44
+ - lib/nswtopo/font/generic.rb
45
+ - lib/nswtopo/formats.rb
46
+ - lib/nswtopo/formats/kmz.rb
47
+ - lib/nswtopo/formats/mbtiles.rb
48
+ - lib/nswtopo/formats/pdf.rb
49
+ - lib/nswtopo/formats/svg.rb
50
+ - lib/nswtopo/formats/svgz.rb
51
+ - lib/nswtopo/formats/zip.rb
52
+ - lib/nswtopo/geometry.rb
53
+ - lib/nswtopo/geometry/overlap.rb
54
+ - lib/nswtopo/geometry/r_tree.rb
55
+ - lib/nswtopo/geometry/segment.rb
56
+ - lib/nswtopo/geometry/straight_skeleton.rb
57
+ - lib/nswtopo/geometry/straight_skeleton/collapse.rb
58
+ - lib/nswtopo/geometry/straight_skeleton/interior_node.rb
59
+ - lib/nswtopo/geometry/straight_skeleton/node.rb
60
+ - lib/nswtopo/geometry/straight_skeleton/nodes.rb
61
+ - lib/nswtopo/geometry/straight_skeleton/split.rb
62
+ - lib/nswtopo/geometry/straight_skeleton/vertex.rb
63
+ - lib/nswtopo/geometry/vector.rb
64
+ - lib/nswtopo/geometry/vector_sequence.rb
65
+ - lib/nswtopo/gis.rb
66
+ - lib/nswtopo/gis/arcgis_server.rb
67
+ - lib/nswtopo/gis/arcgis_server/connection.rb
68
+ - lib/nswtopo/gis/dem.rb
69
+ - lib/nswtopo/gis/esri_hdr.rb
70
+ - lib/nswtopo/gis/gdal_glob.rb
71
+ - lib/nswtopo/gis/geojson.rb
72
+ - lib/nswtopo/gis/geojson/collection.rb
73
+ - lib/nswtopo/gis/geojson/line_string.rb
74
+ - lib/nswtopo/gis/geojson/multi_line_string.rb
75
+ - lib/nswtopo/gis/geojson/multi_point.rb
76
+ - lib/nswtopo/gis/geojson/multi_polygon.rb
77
+ - lib/nswtopo/gis/geojson/point.rb
78
+ - lib/nswtopo/gis/geojson/polygon.rb
79
+ - lib/nswtopo/gis/gps.rb
80
+ - lib/nswtopo/gis/gps/gpx.rb
81
+ - lib/nswtopo/gis/gps/kml.rb
82
+ - lib/nswtopo/gis/projection.rb
83
+ - lib/nswtopo/gis/shapefile.rb
84
+ - lib/nswtopo/gis/world_file.rb
85
+ - lib/nswtopo/help_formatter.rb
86
+ - lib/nswtopo/helpers.rb
87
+ - lib/nswtopo/helpers/array.rb
88
+ - lib/nswtopo/helpers/colour.rb
89
+ - lib/nswtopo/helpers/concurrently.rb
90
+ - lib/nswtopo/helpers/dir.rb
91
+ - lib/nswtopo/helpers/hash.rb
92
+ - lib/nswtopo/helpers/tar_writer.rb
93
+ - lib/nswtopo/layer.rb
94
+ - lib/nswtopo/layer/arcgis_raster.rb
95
+ - lib/nswtopo/layer/contour.rb
96
+ - lib/nswtopo/layer/control.rb
97
+ - lib/nswtopo/layer/declination.rb
98
+ - lib/nswtopo/layer/feature.rb
99
+ - lib/nswtopo/layer/grid.rb
100
+ - lib/nswtopo/layer/import.rb
101
+ - lib/nswtopo/layer/labels.rb
102
+ - lib/nswtopo/layer/labels/fence.rb
103
+ - lib/nswtopo/layer/overlay.rb
104
+ - lib/nswtopo/layer/raster.rb
105
+ - lib/nswtopo/layer/relief.rb
106
+ - lib/nswtopo/layer/spot.rb
107
+ - lib/nswtopo/layer/vector.rb
108
+ - lib/nswtopo/layer/vegetation.rb
109
+ - lib/nswtopo/log.rb
110
+ - lib/nswtopo/map.rb
111
+ - lib/nswtopo/os.rb
112
+ - lib/nswtopo/safely.rb
113
+ - lib/nswtopo/version.rb
114
+ - lib/nswtopo/zip.rb
115
+ homepage: https://github.com/mholling/nswtopo
116
+ licenses:
117
+ - GPL-3.0
118
+ metadata: {}
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: 2.5.0
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">"
131
+ - !ruby/object:Gem::Version
132
+ version: 1.3.1
133
+ requirements:
134
+ - GDAL >= v2.3
135
+ - ImageMagick
136
+ - Google Chrome
137
+ rubyforge_project:
138
+ rubygems_version: 2.7.6
139
+ signing_key:
140
+ specification_version: 4
141
+ summary: A vector topographic mapping tool
142
+ test_files: []