nswtopo 2.0.0.pre.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/COPYING +674 -0
- data/bin/nswtopo +430 -0
- data/docs/README.md +78 -0
- data/docs/add.md +49 -0
- data/docs/config.md +24 -0
- data/docs/contours.md +37 -0
- data/docs/controls.md +9 -0
- data/docs/declination.md +15 -0
- data/docs/delete.md +15 -0
- data/docs/grid.md +5 -0
- data/docs/info.md +5 -0
- data/docs/init.md +38 -0
- data/docs/layers.md +11 -0
- data/docs/overlay.md +37 -0
- data/docs/relief.md +22 -0
- data/docs/render.md +43 -0
- data/docs/spot-heights.md +23 -0
- data/lib/nswtopo/archive.rb +93 -0
- data/lib/nswtopo/avl_tree.rb +128 -0
- data/lib/nswtopo/config.rb +73 -0
- data/lib/nswtopo/dither.rb +31 -0
- data/lib/nswtopo/font/chrome.rb +59 -0
- data/lib/nswtopo/font/generic.rb +25 -0
- data/lib/nswtopo/font.rb +43 -0
- data/lib/nswtopo/formats/kmz.rb +149 -0
- data/lib/nswtopo/formats/mbtiles.rb +64 -0
- data/lib/nswtopo/formats/pdf.rb +31 -0
- data/lib/nswtopo/formats/svg.rb +69 -0
- data/lib/nswtopo/formats/svgz.rb +13 -0
- data/lib/nswtopo/formats/zip.rb +40 -0
- data/lib/nswtopo/formats.rb +76 -0
- data/lib/nswtopo/geometry/overlap.rb +78 -0
- data/lib/nswtopo/geometry/r_tree.rb +47 -0
- data/lib/nswtopo/geometry/segment.rb +27 -0
- data/lib/nswtopo/geometry/straight_skeleton/collapse.rb +21 -0
- data/lib/nswtopo/geometry/straight_skeleton/interior_node.rb +17 -0
- data/lib/nswtopo/geometry/straight_skeleton/node.rb +50 -0
- data/lib/nswtopo/geometry/straight_skeleton/nodes.rb +295 -0
- data/lib/nswtopo/geometry/straight_skeleton/split.rb +33 -0
- data/lib/nswtopo/geometry/straight_skeleton/vertex.rb +9 -0
- data/lib/nswtopo/geometry/straight_skeleton.rb +6 -0
- data/lib/nswtopo/geometry/vector.rb +91 -0
- data/lib/nswtopo/geometry/vector_sequence.rb +179 -0
- data/lib/nswtopo/geometry.rb +8 -0
- data/lib/nswtopo/gis/arcgis_server/connection.rb +52 -0
- data/lib/nswtopo/gis/arcgis_server.rb +155 -0
- data/lib/nswtopo/gis/dem.rb +70 -0
- data/lib/nswtopo/gis/esri_hdr.rb +77 -0
- data/lib/nswtopo/gis/gdal_glob.rb +41 -0
- data/lib/nswtopo/gis/geojson/collection.rb +94 -0
- data/lib/nswtopo/gis/geojson/line_string.rb +11 -0
- data/lib/nswtopo/gis/geojson/multi_line_string.rb +63 -0
- data/lib/nswtopo/gis/geojson/multi_point.rb +12 -0
- data/lib/nswtopo/gis/geojson/multi_polygon.rb +167 -0
- data/lib/nswtopo/gis/geojson/point.rb +9 -0
- data/lib/nswtopo/gis/geojson/polygon.rb +11 -0
- data/lib/nswtopo/gis/geojson.rb +89 -0
- data/lib/nswtopo/gis/gps/gpx.rb +22 -0
- data/lib/nswtopo/gis/gps/kml.rb +66 -0
- data/lib/nswtopo/gis/gps.rb +20 -0
- data/lib/nswtopo/gis/projection.rb +56 -0
- data/lib/nswtopo/gis/shapefile.rb +24 -0
- data/lib/nswtopo/gis/world_file.rb +19 -0
- data/lib/nswtopo/gis.rb +9 -0
- data/lib/nswtopo/help_formatter.rb +59 -0
- data/lib/nswtopo/helpers/array.rb +30 -0
- data/lib/nswtopo/helpers/colour.rb +176 -0
- data/lib/nswtopo/helpers/concurrently.rb +27 -0
- data/lib/nswtopo/helpers/dir.rb +7 -0
- data/lib/nswtopo/helpers/hash.rb +15 -0
- data/lib/nswtopo/helpers/tar_writer.rb +11 -0
- data/lib/nswtopo/helpers.rb +6 -0
- data/lib/nswtopo/layer/arcgis_raster.rb +73 -0
- data/lib/nswtopo/layer/contour.rb +233 -0
- data/lib/nswtopo/layer/control.rb +94 -0
- data/lib/nswtopo/layer/declination.rb +53 -0
- data/lib/nswtopo/layer/feature.rb +87 -0
- data/lib/nswtopo/layer/grid.rb +120 -0
- data/lib/nswtopo/layer/import.rb +25 -0
- data/lib/nswtopo/layer/labels/fence.rb +20 -0
- data/lib/nswtopo/layer/labels.rb +630 -0
- data/lib/nswtopo/layer/overlay.rb +53 -0
- data/lib/nswtopo/layer/raster.rb +63 -0
- data/lib/nswtopo/layer/relief.rb +143 -0
- data/lib/nswtopo/layer/spot.rb +171 -0
- data/lib/nswtopo/layer/vector.rb +263 -0
- data/lib/nswtopo/layer/vegetation.rb +73 -0
- data/lib/nswtopo/layer.rb +78 -0
- data/lib/nswtopo/log.rb +28 -0
- data/lib/nswtopo/map.rb +296 -0
- data/lib/nswtopo/os.rb +75 -0
- data/lib/nswtopo/safely.rb +13 -0
- data/lib/nswtopo/version.rb +4 -0
- data/lib/nswtopo/zip.rb +15 -0
- data/lib/nswtopo.rb +249 -0
- metadata +142 -0
data/bin/nswtopo
ADDED
@@ -0,0 +1,430 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright 2011-2019 Matthew Hollingworth
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
begin
|
19
|
+
require 'open3'
|
20
|
+
require 'optparse'
|
21
|
+
require 'pathname'
|
22
|
+
require 'etc'
|
23
|
+
require 'yaml'
|
24
|
+
require 'rdoc'
|
25
|
+
require_relative '../lib/nswtopo.rb'
|
26
|
+
require_relative '../lib/nswtopo/help_formatter.rb'
|
27
|
+
|
28
|
+
extend NSWTopo::Log
|
29
|
+
Thread::report_on_exception = false
|
30
|
+
|
31
|
+
GDAL_VERSION = begin
|
32
|
+
stdout, * = Open3.capture3 "gdalinfo", "--version"
|
33
|
+
stdout[/\d+(?:\.\d+){1,2}/]
|
34
|
+
rescue Errno::ENOENT
|
35
|
+
log_abort "GDAL not installed"
|
36
|
+
end
|
37
|
+
|
38
|
+
case
|
39
|
+
when (RUBY_VERSION.split(/\D+/).take(3).map(&:to_i) <=> [2,5]) < 0
|
40
|
+
log_abort "ruby 2.5 or greater required"
|
41
|
+
when !Zlib.const_defined?(:GzipFile)
|
42
|
+
log_abort "ruby with GZIP_SUPPORT required"
|
43
|
+
when (GDAL_VERSION.split(/\D+/).take(3).map(&:to_i) <=> [2,3]) < 0
|
44
|
+
log_abort "GDAL 2.3 or greater required"
|
45
|
+
end
|
46
|
+
|
47
|
+
digits = '\d+(?:_\d+)*'
|
48
|
+
float = "[-+]?(?:#{digits}(?=(.)?)(?:\\.(?:#{digits})?)?|\\.#{digits})(?:[eE][-+]?#{digits})?"
|
49
|
+
coords = "#{float},#{float}"
|
50
|
+
|
51
|
+
PositiveInt = /\A#{digits}\z/
|
52
|
+
PositiveFloat = /\A#{float}\z/
|
53
|
+
NonNegFloat = 0..Float::INFINITY
|
54
|
+
Dimensions = /\A#{float},#{float}\z/
|
55
|
+
Margins = /\A#{float}(?:,#{float})?\z/
|
56
|
+
CoordList = /\A#{coords}(?:,#{coords})*\z/
|
57
|
+
Rotation = /\A(?:#{float}|magnetic|auto)\z/
|
58
|
+
AltitudeAngle = 0..90
|
59
|
+
Opacity = /\A#{float}%?\z/
|
60
|
+
DashArray = /\A#{float}(?:(?:,#{float})*|(?: #{float})*)\z/
|
61
|
+
|
62
|
+
OptionParser.accept PositiveInt, PositiveInt do |string|
|
63
|
+
raise OptionParser::InvalidArgument, string unless string.to_i.positive?
|
64
|
+
string.to_i
|
65
|
+
end
|
66
|
+
|
67
|
+
OptionParser.accept PositiveFloat, PositiveFloat do |string|
|
68
|
+
raise OptionParser::InvalidArgument, string unless string.to_f.positive?
|
69
|
+
string.to_f
|
70
|
+
end
|
71
|
+
|
72
|
+
OptionParser.accept NonNegFloat, PositiveFloat do |string|
|
73
|
+
raise OptionParser::InvalidArgument, string if string.to_f.negative?
|
74
|
+
string.to_f
|
75
|
+
end
|
76
|
+
|
77
|
+
OptionParser.accept Dimensions, Dimensions do |string|
|
78
|
+
dimensions = string.split(?,).map(&:to_f)
|
79
|
+
raise OptionParser::InvalidArgument, string unless dimensions.all?(&:positive?)
|
80
|
+
dimensions
|
81
|
+
end
|
82
|
+
|
83
|
+
OptionParser.accept Margins, Margins do |string|
|
84
|
+
margins = string.split(?,).map(&:to_f)
|
85
|
+
raise OptionParser::InvalidArgument, string if margins.any?(&:negative?)
|
86
|
+
margins.one? ? margins * 2 : margins
|
87
|
+
end
|
88
|
+
|
89
|
+
OptionParser.accept CoordList, CoordList do |string|
|
90
|
+
string.split(?,).map(&:to_f).each_slice(2).to_a
|
91
|
+
end
|
92
|
+
|
93
|
+
OptionParser.accept Rotation, Rotation do |string|
|
94
|
+
"magnetic" == string ? string : "auto" == string ? string : string.to_f
|
95
|
+
end
|
96
|
+
|
97
|
+
OptionParser.accept AltitudeAngle, PositiveFloat do |string|
|
98
|
+
raise OptionParser::InvalidArgument, string unless AltitudeAngle === string.to_f
|
99
|
+
string.to_f
|
100
|
+
end
|
101
|
+
|
102
|
+
OptionParser.accept Pathname do |string|
|
103
|
+
path = Pathname(string).expand_path
|
104
|
+
raise OptionParser::InvalidArgument, string unless path.exist?
|
105
|
+
path
|
106
|
+
end
|
107
|
+
|
108
|
+
OptionParser.accept Colour do |string|
|
109
|
+
string == "none" ? string : Colour.new(string.downcase).to_s
|
110
|
+
rescue Colour::Error
|
111
|
+
raise OptionParser::InvalidArgument, string
|
112
|
+
end
|
113
|
+
|
114
|
+
OptionParser.accept Opacity, Opacity do |string|
|
115
|
+
opacity = string.end_with?(?%) ? Float(string.chomp ?%) * 0.01 : Float(string)
|
116
|
+
raise OptionParser::InvalidArgument, string unless (0..1) === opacity
|
117
|
+
opacity
|
118
|
+
end
|
119
|
+
|
120
|
+
OptionParser.accept DashArray, DashArray do |string|
|
121
|
+
values = string.split(/[, ]/).map(&:to_f)
|
122
|
+
raise OptionParser::InvalidArgument, string if values.any?(&:negative?)
|
123
|
+
values.join ?\s
|
124
|
+
end
|
125
|
+
|
126
|
+
ansi = lambda do |string|
|
127
|
+
string.to_s.gsub(/\*([-a-zA-Z0-9]+)\*/) do
|
128
|
+
"\e[1m%s\e[0m" % $1
|
129
|
+
end.gsub(/_([-a-zA-Z0-9]+)_/) do
|
130
|
+
"\e[4m%s\e[0m" % $1
|
131
|
+
end.gsub(/~([-a-zA-Z0-9]+)~/) do
|
132
|
+
"\e[3m%s\e[0m" % $1
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
plain = lambda do |string|
|
137
|
+
string.to_s.gsub(/\*([-a-zA-Z0-9]+)\*/) { $1 }.gsub(/_([-a-zA-Z0-9]+)_/) { $1 }.gsub(/~([-a-zA-Z0-9]+)~/) { $1 }
|
138
|
+
end
|
139
|
+
|
140
|
+
base_parser = OptionParser.new do |parser|
|
141
|
+
parser.separator " options:"
|
142
|
+
parser.banner = <<~EOF
|
143
|
+
*nswtopo* - download and create vector topographic maps
|
144
|
+
usage: _nswtopo_ [~options~] [<command> ...]
|
145
|
+
commands:
|
146
|
+
init initialise map bounds and scale
|
147
|
+
info display map layers and metadata
|
148
|
+
add add named map layer
|
149
|
+
contours add contours from elevation data
|
150
|
+
spot-heights add spot heights from elevation data
|
151
|
+
relief add shaded relief
|
152
|
+
grid add UTM grid
|
153
|
+
declination add magnetic declination lines
|
154
|
+
controls add rogaine control markers
|
155
|
+
overlay add KML or GPX overlay
|
156
|
+
delete delete map layer
|
157
|
+
render render map in various formats
|
158
|
+
layers list available map layers
|
159
|
+
config configure nswtopo
|
160
|
+
command help: _nswtopo_ <command> --help
|
161
|
+
EOF
|
162
|
+
parser.on "-v", "--version", "show version information" do
|
163
|
+
puts NSWTopo::VERSION
|
164
|
+
exit
|
165
|
+
end
|
166
|
+
parser.on "-q", "--quiet", "suppress non-error output" do
|
167
|
+
$stdout = File.open(File::NULL, "w")
|
168
|
+
end
|
169
|
+
parser.on "-c", "--config <path>", Pathname, "load extra configuration" do |path|
|
170
|
+
NSWTopo::Config.extra_path = path
|
171
|
+
end
|
172
|
+
parser.on "-h", "--help", "show general help" do
|
173
|
+
puts $stdout.tty? ? ansi[parser] : plain[parser]
|
174
|
+
doc = Pathname(__dir__).parent / "docs" / "README.md"
|
175
|
+
puts nil, RDoc::Markdown.parse(doc.read encoding: Encoding::UTF_8).accept(HelpFormatter.new $stdout.tty?)
|
176
|
+
exit
|
177
|
+
end
|
178
|
+
end
|
179
|
+
base_parser.order!
|
180
|
+
|
181
|
+
command, options = ARGV.shift, Hash.new
|
182
|
+
command_parser = OptionParser.new do |parser|
|
183
|
+
parser.separator " options:"
|
184
|
+
|
185
|
+
case command
|
186
|
+
when "init"
|
187
|
+
parser.banner = <<~EOF
|
188
|
+
*nswtopo* *init* - initialise map bounds and scale
|
189
|
+
usage: _nswtopo_ _init_ [~options~] <map.tgz>
|
190
|
+
EOF
|
191
|
+
parser.on "-s", "--scale <scale>", PositiveInt, "scale of map (default 25000)"
|
192
|
+
parser.on "-b", "--bounds <bounds.kml>", Pathname, "bounds for map as KML or GPX file"
|
193
|
+
parser.on "-c", "--coords <x1,y1,...>", CoordList, "bounds for map as one or more WGS84",
|
194
|
+
"longitude/latitude pairs"
|
195
|
+
parser.on "-d", "--dimensions <width,height>", Dimensions, "dimensions of map in mm"
|
196
|
+
parser.on "-m", "--margins <x[,y]>", Margins, "map margins in mm"
|
197
|
+
parser.on "-r", "--rotation <rotation>", Rotation, "map rotation angle in clockwise",
|
198
|
+
"degrees, 'auto' or 'magnetic'"
|
199
|
+
parser.on "-o", "--overwrite", "overwrite existing map file"
|
200
|
+
|
201
|
+
when "info"
|
202
|
+
parser.banner = <<~EOF
|
203
|
+
*nswtopo* *info* - display map layers and metadata
|
204
|
+
usage: _nswtopo_ _info_ [~options~] <map.tgz>
|
205
|
+
EOF
|
206
|
+
parser.on "-e", "--empty", "show empty layers"
|
207
|
+
|
208
|
+
when "add"
|
209
|
+
parser.banner = <<~EOF
|
210
|
+
*nswtopo* *add* - add named map layer
|
211
|
+
usage: _nswtopo_ _add_ [~options~] <map.tgz> <layer> [<layer> ...]
|
212
|
+
EOF
|
213
|
+
parser.on "-r", "--resolution <resolution>", PositiveFloat, "raster layer resolution in metres"
|
214
|
+
parser.on "-p", "--path <path>", Pathname, "source data path for layer"
|
215
|
+
parser.on "-a", "--after <layer>", "insert after specified layer"
|
216
|
+
parser.on "-b", "--before <layer>", "insert before specified layer"
|
217
|
+
parser.on "-c", "--replace <layer>", "replace specified layer"
|
218
|
+
parser.on "-o", "--overwrite", "overwrite layer if it already exists"
|
219
|
+
|
220
|
+
when "contours"
|
221
|
+
parser.banner = <<~EOF
|
222
|
+
*nswtopo* *contours* - add contours from elevation data
|
223
|
+
usage: _nswtopo_ _contours_ [~options~] <map.tgz> <dem.zip>
|
224
|
+
EOF
|
225
|
+
parser.on "-i", "--interval <interval>", PositiveInt, "contour interval in metres (default %s)" % NSWTopo::Contour::DEFAULTS["interval"]
|
226
|
+
parser.on "-x", "--index <index>", PositiveInt, "index interval in metres"
|
227
|
+
parser.on "-s", "--smooth <radius>", NonNegFloat, "DEM smoothing radius in mm (default %s)" % NSWTopo::Contour::DEFAULTS["smooth"]
|
228
|
+
parser.on "-t", "--thin", "thin intermediate contours in steep areas"
|
229
|
+
# parser.on "-d", "--density <density>", PositiveFloat, "maximum lines/mm before thinning occurs"
|
230
|
+
# parser.on "-m", "--min-length <length>", PositiveFloat, "minimum length before contour thinning in mm"
|
231
|
+
parser.on "--no-depression", "don't show or clean depression contours"
|
232
|
+
parser.on "-k", "--knolls <size>", NonNegFloat, "minimum knoll size in mm (default %s)" % NSWTopo::Contour::DEFAULTS["knolls"]
|
233
|
+
parser.on "-a", "--after <layer>", "insert after specified layer"
|
234
|
+
parser.on "-b", "--before <layer>", "insert before specified layer"
|
235
|
+
parser.on "-c", "--replace <layer>", "replace specified layer"
|
236
|
+
parser.on "--stroke <colour>", Colour, "stroke colour (name or RGB triplet)"
|
237
|
+
parser.on "--stroke-width <width>", PositiveFloat, "stroke width in mm"
|
238
|
+
parser.on "--fill <colour>", Colour, "label colour (defaults to stroke colour)"
|
239
|
+
|
240
|
+
when "spot-heights"
|
241
|
+
parser.banner = <<~EOF
|
242
|
+
*nswtopo* *spot-heights* - add spot heights from elevation data
|
243
|
+
usage: _nswtopo_ _spot-heights_ [~options~] <map.tgz> <dem.zip>
|
244
|
+
EOF
|
245
|
+
parser.on "-s", "--smooth <radius>", NonNegFloat, "DEM smoothing radius in mm (default %s)" % NSWTopo::Spot::DEFAULTS["smooth"]
|
246
|
+
parser.on "--spacing <spacing>", PositiveFloat, "minimum spot spacing in mm (default %i)" % NSWTopo::Spot::DEFAULTS["spacing"]
|
247
|
+
parser.on "-p", "--prefer <knolls|saddles>", %w[knolls saddles], "preferred spot locations"
|
248
|
+
parser.on "-a", "--after <layer>", "insert after specified layer"
|
249
|
+
parser.on "-b", "--before <layer>", "insert before specified layer"
|
250
|
+
parser.on "-c", "--replace <layer>", "replace specified layer"
|
251
|
+
|
252
|
+
when "relief"
|
253
|
+
parser.banner = <<~EOF
|
254
|
+
*nswtopo* *relief* - add shaded relief
|
255
|
+
usage: _nswtopo_ _relief_ [~options~] <map.tgz> <dem.zip>
|
256
|
+
EOF
|
257
|
+
parser.on "-r", "--resolution <resolution>", PositiveFloat, "resolution in metres (default %i)" % NSWTopo::Relief::DEFAULTS["resolution"]
|
258
|
+
parser.on "-o", "--opacity <opacity>", Opacity, "opacity (default %s)" % NSWTopo::Relief::DEFAULTS["opacity"]
|
259
|
+
parser.on "-a", "--altitude <altitude>", AltitudeAngle, "altitude angle in degrees (default %i)" % NSWTopo::Relief::DEFAULTS["altitude"]
|
260
|
+
parser.on "-z", "--azimuth <azimuth>", Float, "azimuth in degrees (default %i)" % NSWTopo::Relief::DEFAULTS["azimuth"]
|
261
|
+
parser.on "-s", "--sources <sources>", PositiveInt, "number of light sources (default %i)" % NSWTopo::Relief::DEFAULTS["sources"]
|
262
|
+
parser.on "-y", "--yellow <fraction>", Opacity, "yellow illumination as a fraction",
|
263
|
+
"of shading (default %s)" % NSWTopo::Relief::DEFAULTS["yellow"]
|
264
|
+
parser.on "-f", "--factor <factor>", PositiveFloat, "exaggeration factor (default %s)" % NSWTopo::Relief::DEFAULTS["factor"]
|
265
|
+
|
266
|
+
when "grid"
|
267
|
+
parser.banner = <<~EOF
|
268
|
+
*nswtopo* *grid* - add UTM grid
|
269
|
+
usage: _nswtopo_ _grid_ [~options~] <map.tgz>
|
270
|
+
EOF
|
271
|
+
parser.on "-i", "--interval <interval>", PositiveFloat, "interval between grid lines in",
|
272
|
+
"metres (default %i)" % NSWTopo::Grid::DEFAULTS["interval"]
|
273
|
+
|
274
|
+
when "declination"
|
275
|
+
parser.banner = <<~EOF
|
276
|
+
*nswtopo* *declination* - add magnetic declination lines
|
277
|
+
usage: _nswtopo_ _declination_ [~options~] <map.tgz>
|
278
|
+
EOF
|
279
|
+
parser.on "-a", "--angle <angle>", Float, "magnetic declination in clockwise degrees",
|
280
|
+
"(calculated automatically by default)"
|
281
|
+
parser.on "-s", "--spacing <spacing>", PositiveFloat, "spacing of lines in mm (default %i)" % NSWTopo::Declination::DEFAULTS["spacing"]
|
282
|
+
parser.on "-o", "--offset <offset>", Float, "rightwards offset of lines in mm"
|
283
|
+
parser.on "-r", "--arrows <arrows>", PositiveFloat, "spacing of arrows in mm (default %i)" % NSWTopo::Declination::DEFAULTS["arrows"]
|
284
|
+
parser.on "--stroke <colour>", Colour, "stroke colour (name or RGB triplet)"
|
285
|
+
|
286
|
+
when "controls"
|
287
|
+
parser.banner = <<~EOF
|
288
|
+
*nswtopo* *controls* - add rogaine control markers
|
289
|
+
usage: _nswtopo_ _controls_ [~options~] <map.tgz> <controls.gpx>
|
290
|
+
EOF
|
291
|
+
parser.on "-d", "--diameter <diameter>", PositiveFloat, "diameter of markers in mm (default %s)" % NSWTopo::Control::DEFAULTS["diameter"]
|
292
|
+
parser.on "-s", "--spot", "add spots at centres"
|
293
|
+
parser.on "-c", "--colour <colour>", Colour, "colour of markers and labels",
|
294
|
+
"(name or RGB triplet)"
|
295
|
+
parser.on "-f", "--font-size <font-size>", PositiveFloat, "font size for labels in mm"
|
296
|
+
|
297
|
+
when "overlay"
|
298
|
+
parser.banner = <<~EOF
|
299
|
+
*nswtopo* *overlay* - add KML or GPX overlay
|
300
|
+
usage: _nswtopo_ _overlay_ [~options~] <map.tgz> <overlay.kml>
|
301
|
+
EOF
|
302
|
+
parser.on "--opacity <opacity>", Opacity, "layer opacity (between 0 and 1)"
|
303
|
+
parser.on "--stroke <colour>", Colour, "stroke colour (name or RGB triplet)"
|
304
|
+
parser.on "--stroke-width <width>", PositiveFloat, "stroke width in mm"
|
305
|
+
parser.on "--stroke-opacity <opacity>", Opacity, "stroke opacity"
|
306
|
+
parser.on "--stroke-dasharray <mm,...>", DashArray, "stroke dash sequence in mm"
|
307
|
+
parser.on "--stroke-linecap <butt|round|square>", %w[butt round square],
|
308
|
+
"stroke linecap value"
|
309
|
+
parser.on "--fill <colour>", Colour, "polygon fill colour"
|
310
|
+
parser.on "--fill-opacity <opacity>", Opacity, "polygon fill opacity"
|
311
|
+
parser.on "-s", "--simplify", "apply track simplification"
|
312
|
+
parser.on "-t", "--tolerance <metres>", PositiveFloat, "track simplifiction tolerance in metres",
|
313
|
+
"(scale-appropriate value used by default)"
|
314
|
+
parser.on "-a", "--after <layer>", "insert after specified layer"
|
315
|
+
parser.on "-b", "--before <layer>", "insert before specified layer"
|
316
|
+
parser.on "-c", "--replace <layer>", "replace specified layer"
|
317
|
+
|
318
|
+
when "delete"
|
319
|
+
parser.banner = <<~EOF
|
320
|
+
*nswtopo* *delete* - delete map layers
|
321
|
+
usage: _nswtopo_ _delete_ [~options~] <map.tgz> <layer> [<layer> ...]
|
322
|
+
EOF
|
323
|
+
|
324
|
+
when "render"
|
325
|
+
parser.banner = <<~EOF
|
326
|
+
*nswtopo* *render* - render map in various formats
|
327
|
+
usage: _nswtopo_ _render_ [~options~] <map.tgz> [<format-or-path> ...]
|
328
|
+
formats: #{NSWTopo::Formats.extensions.sort.join ?\s}
|
329
|
+
default: svg
|
330
|
+
EOF
|
331
|
+
parser.on "-p", "--ppi <ppi>", PositiveInt, "resolution for raster formats in pixels",
|
332
|
+
"per inch (default %i)" % NSWTopo::Formats::PPI
|
333
|
+
parser.on "-z", "--zoom <zoom>", Integer, "maximum mbtiles zoom level (default %i)" % NSWTopo::Formats::Mbtiles::ZOOM
|
334
|
+
parser.on "-d", "--dither", "use indexed colour for raster formats"
|
335
|
+
parser.on "-w", "--worldfile", "save additional projection (.prj) and",
|
336
|
+
"world file (.wld) for raster formats"
|
337
|
+
parser.on "-o", "--overwrite", "overwrite existing output files"
|
338
|
+
parser.on "-e", "--external <map.svg>", Pathname, "render from externally edited SVG"
|
339
|
+
parser.on "-f", "--force", "force regeneration of cached SVG"
|
340
|
+
|
341
|
+
when "layers"
|
342
|
+
parser.banner = <<~EOF
|
343
|
+
*nswtopo* *layers* - list available map layers
|
344
|
+
usage: _nswtopo_ _layers_ [~options~]
|
345
|
+
EOF
|
346
|
+
|
347
|
+
when "config"
|
348
|
+
parser.banner = <<~EOF
|
349
|
+
*nswtopo* *config* - configure nswtopo
|
350
|
+
usage: _nswtopo_ _config_ [~options~] [<layer>]
|
351
|
+
EOF
|
352
|
+
parser.on "-d", "--delete <name>", "delete configuration setting"
|
353
|
+
parser.on "-c", "--chrome <path>", Pathname, "set path for Google Chrome"
|
354
|
+
parser.on "-f", "--firefox <path>", Pathname, "set path for Firefox"
|
355
|
+
parser.on "-p", "--path <path>", Pathname, "set path for given layer"
|
356
|
+
parser.on "-r", "--resolution <resolution>", PositiveFloat, "set resolution for given layer"
|
357
|
+
parser.on "--layer-dir <path>", Pathname, "set an extra layer directory"
|
358
|
+
parser.on "--[no-]labelling", "enable or disable map labelling"
|
359
|
+
|
360
|
+
when nil
|
361
|
+
raise OptionParser::MissingArgument, "no command specified"
|
362
|
+
|
363
|
+
else
|
364
|
+
raise OptionParser::InvalidArgument, command
|
365
|
+
end
|
366
|
+
|
367
|
+
parser.on "-h", "--help", "show help for this command" do
|
368
|
+
puts $stdout.tty? ? ansi[parser] : plain[parser]
|
369
|
+
doc = Pathname(__dir__).parent / "docs" / "#{command}.md"
|
370
|
+
puts nil, RDoc::Markdown.parse(doc.read encoding: Encoding::UTF_8).accept(HelpFormatter.new $stdout.tty?)
|
371
|
+
rescue Errno::ENOENT
|
372
|
+
ensure
|
373
|
+
exit
|
374
|
+
end
|
375
|
+
rescue OptionParser::ParseError => error
|
376
|
+
warn ansi[base_parser] if $stderr.tty?
|
377
|
+
raise error.message
|
378
|
+
end
|
379
|
+
command_parser.parse! into: options
|
380
|
+
|
381
|
+
case command
|
382
|
+
when "layers"
|
383
|
+
raise OptionParser::NeedlessArgument, ARGV if ARGV.any?
|
384
|
+
NSWTopo.layers options
|
385
|
+
exit
|
386
|
+
when "config"
|
387
|
+
layer = ARGV.shift
|
388
|
+
raise OptionParser::NeedlessArgument, ARGV if ARGV.any?
|
389
|
+
NSWTopo.config *layer, **options
|
390
|
+
exit
|
391
|
+
end
|
392
|
+
|
393
|
+
raise OptionParser::MissingArgument, "no map path specified" if ARGV.empty?
|
394
|
+
tgz_path = Pathname(ARGV.shift)
|
395
|
+
|
396
|
+
begin
|
397
|
+
in_path = case command
|
398
|
+
when "init"
|
399
|
+
raise "#{tgz_path} already exists" if !options.delete(:overwrite) && tgz_path.exist?
|
400
|
+
else
|
401
|
+
raise "no such file #{tgz_path}" unless tgz_path.exist?
|
402
|
+
raise "#{tgz_path} is not a file" unless tgz_path.file?
|
403
|
+
tgz_path
|
404
|
+
end
|
405
|
+
|
406
|
+
command = command.tr ?-, ?_
|
407
|
+
arity, error = NSWTopo.method(command).arity, nil
|
408
|
+
|
409
|
+
NSWTopo::Archive.open(tgz_path, *in_path) do |archive|
|
410
|
+
args = [archive, *ARGV, options]
|
411
|
+
case
|
412
|
+
when arity >= 0 && args.length > arity
|
413
|
+
raise OptionParser::NeedlessArgument, ARGV.last(args.length - arity).join(?\s)
|
414
|
+
when arity >= 0 ? args.length < arity : args.length + arity + 1 < 0
|
415
|
+
raise OptionParser::MissingArgument
|
416
|
+
end
|
417
|
+
|
418
|
+
NSWTopo.send command, *args
|
419
|
+
rescue NSWTopo::PartialFailureError => error
|
420
|
+
end
|
421
|
+
raise error.message if error
|
422
|
+
end
|
423
|
+
rescue OptionParser::ParseError => error
|
424
|
+
warn ansi[command_parser] if $stderr.tty?
|
425
|
+
log_abort error.message
|
426
|
+
rescue Interrupt
|
427
|
+
abort $stderr.tty? ? "\r\e[K\e[31mnswtopo:\e[0m interrupted" : "nswtopo: interrupted"
|
428
|
+
rescue RuntimeError => error
|
429
|
+
log_abort error.message
|
430
|
+
end
|
data/docs/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# Description
|
2
|
+
|
3
|
+
Use *nswtopo* to create vector topographic maps of NSW and other states. Various *commands* allow you to initialise your map, add layers and render outputs in a number of formats. Pre-designed map layers download topographic data from internet maps servers and local sources.
|
4
|
+
|
5
|
+
# Commands
|
6
|
+
|
7
|
+
Help screens are available describing usage for each commands. Use the `--help` option with the command:
|
8
|
+
|
9
|
+
```
|
10
|
+
$ nswtopo init --help
|
11
|
+
```
|
12
|
+
|
13
|
+
# Configuration
|
14
|
+
|
15
|
+
An important initial step is to configure the location of *Google Chrome* on your PC. Chrome is required for rendering the map in most formats. Use the *configure* command to set the path:
|
16
|
+
|
17
|
+
```
|
18
|
+
$ nswtopo config --chrome "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
19
|
+
nswtopo: configuration updated
|
20
|
+
```
|
21
|
+
|
22
|
+
Use forward slashes for paths, even on Windows.
|
23
|
+
|
24
|
+
# Map Files
|
25
|
+
|
26
|
+
Most commands need a map file to work on. Name this file anything you want. A `.tgz` extension is suggested, as the file is in *gzipped tar* archive format. All map contents are contained within the file, so a separate directory per map is not necessary.
|
27
|
+
|
28
|
+
# Example
|
29
|
+
|
30
|
+
A typical map creation sequence might look as follows. We initialise the map from a bounds file, add several layers and finally produce an output SVG:
|
31
|
+
|
32
|
+
```
|
33
|
+
$ nswtopo init -b bounds.kml map.tgz
|
34
|
+
scale: 1:25000
|
35
|
+
dimensions: 433mm × 509mm
|
36
|
+
extent: 10.8km × 12.7km
|
37
|
+
area: 138.0km²
|
38
|
+
rotation: 0.0°
|
39
|
+
```
|
40
|
+
|
41
|
+
```
|
42
|
+
$ nswtopo add map.tgz nsw/vegetation-spot5
|
43
|
+
nswtopo: added layer: nsw.vegetation-spot5
|
44
|
+
```
|
45
|
+
|
46
|
+
```
|
47
|
+
$ nswtopo add map.tgz nsw/topographic
|
48
|
+
nswtopo: added layer: nsw.topographic.plantation-horticulture
|
49
|
+
nswtopo: added layer: nsw.topographic.urban-areas
|
50
|
+
...
|
51
|
+
nswtopo: added layer: nsw.topographic.spot-heights
|
52
|
+
```
|
53
|
+
|
54
|
+
```
|
55
|
+
$ nswtopo declination map.tgz
|
56
|
+
nswtopo: added layer: declination
|
57
|
+
```
|
58
|
+
|
59
|
+
```
|
60
|
+
$ nswtopo add map.tgz controls.gpx
|
61
|
+
nswtopo: added layer: controls
|
62
|
+
```
|
63
|
+
|
64
|
+
```
|
65
|
+
$ nswtopo relief map.tgz DATA_25994.zip
|
66
|
+
nswtopo: added layer: relief
|
67
|
+
```
|
68
|
+
|
69
|
+
```
|
70
|
+
$ nswtopo contours -i 5 -x 50 --replace nsw.topographic.contours map.tgz DATA_25994.zip
|
71
|
+
nswtopo: added layer: contours
|
72
|
+
```
|
73
|
+
|
74
|
+
```
|
75
|
+
$ nswtopo render map.tgz svg
|
76
|
+
nswtopo: created map.svg
|
77
|
+
```
|
78
|
+
|
data/docs/add.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Description
|
2
|
+
|
3
|
+
Use this command to add named layers to the map from among those distributed with *nswtopo*. Refer to the website for a description of the various layers. Use the `nswtopo layers` command to display a list of available layers.
|
4
|
+
|
5
|
+
Layers are arranged hierarchically, with some layers being shorthand for a collection of other layers. For example, the `nsw/topographic` layer contains a large number of component layers, such as `nsw/topographic/roads`, `nsw/topographic/watercourses` etc.
|
6
|
+
|
7
|
+
The forward-slash character is used indicate the nested folder structure of these layers. However, once added to the map, these layers are renamed with periods (`nsw.topographic.watercourses`), and the use of period and slash characters is interchangeable.
|
8
|
+
|
9
|
+
# Options
|
10
|
+
|
11
|
+
Some layers, such as vegetation layers, require a dataset to be present on your computer. Specify the location of the dataset with the `--path` option. The path can be absolute, or relative to the working directory.
|
12
|
+
|
13
|
+
Raster layers (vegetation, shaded relief) typically have an appropriate image resolution set for that data. If desired, you can choose a different value using the `--resolution` option. Resolution is in metres per pixel, indicating the dataset quality rather than an output resolution such as pixels per inch.
|
14
|
+
|
15
|
+
For repeated use, it's easier to set the path or resolution for a layer in a permanent configuration file. Use the *config* command for this task.
|
16
|
+
|
17
|
+
# Positioning Layers
|
18
|
+
|
19
|
+
By default, layers are added to the map in an appropriate position for the type: vegetation and aerial layers first, followed by topographic feature layers, overlays, shaded relief, grid, declination and controls.
|
20
|
+
|
21
|
+
To instead select a specific position for the new layer, use the `--after` or `--before` option with an existing layer name. For example, to insert a KML overlay between existing topographic layers:
|
22
|
+
|
23
|
+
```
|
24
|
+
$ nswtopo add --after nsw.topographic.urban-areas map.tgz new-suburb.kml
|
25
|
+
```
|
26
|
+
|
27
|
+
# Other Layers
|
28
|
+
|
29
|
+
While *grid*, *declination*, overlay and *controls* layers each have a dedicated command, it's possible to add them directly if you don't need to change default settings:
|
30
|
+
|
31
|
+
```
|
32
|
+
$ nswtopo add map.tgz out-of-bounds.kml grid controls.gpx
|
33
|
+
```
|
34
|
+
|
35
|
+
Georeferenced rasters (e.g. GeoTIFFs) can also be added directly:
|
36
|
+
|
37
|
+
```
|
38
|
+
$ nswtopo add map.tgz underlay.tif
|
39
|
+
```
|
40
|
+
|
41
|
+
For advanced users, custom layer definitions can added by referencing the `.yml` definition file:
|
42
|
+
|
43
|
+
```
|
44
|
+
$ nswtopo add --after nsw.topographic.water-areas map.tgz bathymetry.yml
|
45
|
+
```
|
46
|
+
|
47
|
+
# Failed Layers
|
48
|
+
|
49
|
+
Map servers can sometimes be uncooperative, resulting in layers which fail to download. In this event, simply run the `add` command again to retry the failed layers. Existing layers will not be re-downloaded.
|
data/docs/config.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Description
|
2
|
+
|
3
|
+
Configure and view permanent *nswtopo* settings using the *config* command. For example, to set the *Google Chrome* path for rendering maps:
|
4
|
+
|
5
|
+
```
|
6
|
+
$ nswtopo config --chrome "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
7
|
+
nswtopo: configuration updated
|
8
|
+
```
|
9
|
+
|
10
|
+
To set the path for a vegetation dataset:
|
11
|
+
|
12
|
+
```
|
13
|
+
$ nswtopo config --path ~/SPOT5/s5hgps_nsw_y20082012_bcvl0.tif nsw.vegetation-spot5
|
14
|
+
nswtopo: configuration updated
|
15
|
+
```
|
16
|
+
|
17
|
+
To review your current configuration:
|
18
|
+
|
19
|
+
```
|
20
|
+
$ nswtopo config
|
21
|
+
chrome: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
22
|
+
nsw.vegetation-spot5:
|
23
|
+
path: "/Users/matthew/SPOT5/s5hgps_nsw_y20082012_bcvl0.tif"
|
24
|
+
```
|
data/docs/contours.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Description
|
2
|
+
|
3
|
+
Generate contour lines directly from a Digital Elevation Model (DEM) with the *contours* command. Any DEM in a planar projection can be used, but high-resolution data is needed for good results.
|
4
|
+
|
5
|
+
# Obtaining the DEM
|
6
|
+
Use the *ELVIS* website [http://elevation.fsdf.org.au] to download DEM tiles for any NSW location. The NSW 2-metre and 5-metre tiles are ideal. 1-metre NSW and ACT tiles also work but are more detailed than necessary. (Do not download Geoscience Australia tiles or point-cloud data.)
|
7
|
+
|
8
|
+
DEM tiles from the ELVIS website are delivered as doubly-zipped files. It's not necessary to unzip the download, although unzipping the first level to a folder will improve processing time.
|
9
|
+
|
10
|
+
# Contour Configuration
|
11
|
+
Choose a contour interval in metres using the `--interval` option. A five metre interval is recommended as it conveys excellent detail and is not too dense for 1:25000 maps in most areas. Specify an index contour interval with the `--index` option.
|
12
|
+
|
13
|
+
Noise in raw elevation data usually produces unsuitably rough contour lines. Some smoothing of the DEM removes most such artefacts. A default smoothing radius of 0.2mm is applied, configurable with the `--smooth` option. Increase the radius to produce smoother contours at the expense of detail.
|
14
|
+
|
15
|
+
# Layer Position
|
16
|
+
|
17
|
+
Use an `--after`, `--before` or `--replace` option to insert the contours in an appropriate layer position. You will most likely want to replace an existing contour layer:
|
18
|
+
|
19
|
+
```
|
20
|
+
$ nswtopo contours --replace nsw.topographic.contours map.tgz DATA_25994.zip
|
21
|
+
```
|
22
|
+
# Style
|
23
|
+
|
24
|
+
Contours are rendered in brown at a thickness of 0.08mm. Change line colour with `--stroke`, thickness with `--stroke-width` and label colour with `--fill`. Colour can be an *RGB triplet* (e.g. *800080*) or *web colour* name (e.g. *purple*).
|
25
|
+
|
26
|
+
# Contour Thinning
|
27
|
+
A small contour interval can produce very dense contours in steep terrain. An advanced `--thin` option is available to selectively remove contours in steep areas such as cliffsides. It emulates a manual contour thinning technique. An index multiple of eight (e.g. 5m contours with 40m index contours) produces the most aesthetic results.
|
28
|
+
|
29
|
+
(*GDAL* with *SpatiaLite* and *GEOS* support is required to perform contour thinning.)
|
30
|
+
|
31
|
+
# Knolls & Depressions
|
32
|
+
|
33
|
+
Contours generated from a DEM can include depression artefacts, most noticeabley at pinch-points in flat or closed-in watercourses. These do not usually represent true depression contours, which are rare. Any isolated depression contours are automatically detected and removed. All nested depression contours are retained and rendered as true depression contours. This behaviour can be disabled with the `--no-depression` option.
|
34
|
+
|
35
|
+
Contours for tiny knolls are also removed. Use the `--knolls` option to specify the minimum size for knolls to be retained.
|
36
|
+
|
37
|
+
When creating contours from a DEM, it's recommended to also generate a new spot heights layer. Use the *spot-heights* command to generate them using the same DEM.
|
data/docs/controls.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Description
|
2
|
+
|
3
|
+
Add rogaine controls to a map with the *controls* command. Collect your control waypoints in a GPX or KML file. *Google Earth* is useful for managing and naming your waypoints during course-setting.
|
4
|
+
|
5
|
+
# Naming
|
6
|
+
Any waypoint with a two- or three-digit name will be identified and marked as a control. Name a waypoint as *HH* or *ANC* to identify it as the hash house or all-night cafe. Suffix any control name with *W*, or have a separate waypoint so named, to identify it as a water drop.
|
7
|
+
|
8
|
+
# Styling
|
9
|
+
Controls are marked and labelled in the conventional style. You can change aspects of this style with the `--diameter`, `--colour` and `--font-size` options. The `--spot` option adds a centre spot for each control.
|
data/docs/declination.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Description
|
2
|
+
|
3
|
+
Use the *declination* command to add lines of magnetic declination to the map. These are useful primarily in rogaining maps, where they facilitate compass bearings.
|
4
|
+
|
5
|
+
# Declination Angle
|
6
|
+
|
7
|
+
The magnetic declination angle is obtained from the NOAA online calculator using the World Magnetic Model. An accuracy of ±0.5° is typical. In the event that the calculator is offline, you can provide a declination angle manually using the `--angle` option.
|
8
|
+
|
9
|
+
# Appearance
|
10
|
+
|
11
|
+
Declination lines are spaced at one-kilometre intervals, or according to the `--spacing` option if passed. Small directional arrows are provided periodically along each line at 160mm intervals.
|
12
|
+
|
13
|
+
The `--offset` option shifts the lines along the horizontal, if fine-tuning is required.
|
14
|
+
|
15
|
+
Change colour using the `--stroke` option, with an *RGB triplet* (e.g. *800080*) or *web colour* name (e.g. *purple*).
|
data/docs/delete.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Description
|
2
|
+
|
3
|
+
Use the *delete* command to delete layers from the map. Specify the name of the layer or layers you wish to delete:
|
4
|
+
|
5
|
+
```
|
6
|
+
$ nswtopo delete map.tgz nsw.relief grid
|
7
|
+
```
|
8
|
+
|
9
|
+
When deleting multiple layers, a form of wildcard is also available:
|
10
|
+
|
11
|
+
```
|
12
|
+
$ nswtopo delete map.tgz "nsw.topographic.*"
|
13
|
+
```
|
14
|
+
|
15
|
+
Use the *info* command to see the names of layers currently in the map file.
|