nswtopo 3.1 → 3.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c90485c22ed73dd281bbb6abb7dafd9ec919edda7065dd7106b0acd12485acf3
4
- data.tar.gz: fc3bae27f7d28243a3e9e27e56c28c8c0a724ea92237c018e4b161c9ad1ee74a
3
+ metadata.gz: 8f6740cf4e3532418e42aff410453d38a26cbdd2cb087a7ee7d753ca6d252d13
4
+ data.tar.gz: 6968cbfab11ce7d74f4d75ad53a562d89730a8551ae6baea6c8ea6360a010dc2
5
5
  SHA512:
6
- metadata.gz: 70779d0482c7d5350f65af71faa1503f3f290125e38bbe16e9017c10332da375e763ac4583907f43e741b612f928563379c32b7ec38652b22ffe2d2d34827519
7
- data.tar.gz: d67a0b8e445cfec80c7ccae5d3df98983ec82b5533188e07e232f8dc41f825d70cc98026b5bb566127256eb22d4721e0aa1f697cccd80f98a85ee6cea8fdb006
6
+ metadata.gz: f250d4a093f83d06c9b606c012a05e35739e6fca2805a0abe95c2129a7bffd0edb530c60d3262ca5716e32bb7d2d7a69e6e4e27756e2f81ce49ba0f9ca34baff
7
+ data.tar.gz: 20b7ac67eee937b5c273c17029ce441e8912dddd2ad75f3ea58ead8ed54b132f2466a15ac0e2f68d3e38a26de139cd5cd1106478db2d0735b9d852b5c3404fc5
data/bin/nswtopo CHANGED
@@ -41,8 +41,8 @@ begin
41
41
  log_abort "ruby 3.1.4 or greater required"
42
42
  when !Zlib.const_defined?(:GzipFile)
43
43
  log_abort "ruby with GZIP_SUPPORT required"
44
- when (GDAL_VERSION.split(/\D+/).take(3).map(&:to_i) <=> [3,4]) < 0
45
- log_abort "GDAL 3.4 or greater required"
44
+ when (GDAL_VERSION.split(/\D+/).take(3).map(&:to_i) <=> [3,8]) < 0
45
+ log_abort "GDAL 3.8 or greater required"
46
46
  end
47
47
 
48
48
  digits = '\d+(?:_\d+)*'
@@ -220,6 +220,7 @@ begin
220
220
  parser.on "-b", "--bounds <bounds.kml>", Pathname, "bounds for map as KML or GPX file"
221
221
  parser.on "-c", "--coords <x1,y1,...>", CoordList, "bounds for map as one or more WGS84",
222
222
  "longitude/latitude pairs"
223
+ parser.on "-n", "--neatline <neatline.kml>", Pathname, "neatline for map as KML file"
223
224
  parser.on "-d", "--dimensions <width,height>", Dimensions, "map dimensions in mm"
224
225
  parser.on "-r", "--rotation <rotation>", Rotation, "map rotation angle in clockwise",
225
226
  "degrees, 'auto' or 'magnetic'"
@@ -29,7 +29,7 @@ module NSWTopo
29
29
  queue = Queue.new
30
30
  thread = Thread.new do
31
31
  while page = queue.pop
32
- *, status = Open3.capture3 *%W[ogr2ogr #{path} /vsistdin/], *flags, *format_flags, stdin_data: page.to_json
32
+ *, status = Open3.capture3 *%W[ogr2ogr #{path} /vsistdin?buffer_limit=-1], *flags, *format_flags, stdin_data: page.to_json
33
33
  format_flags = %w[-update -append]
34
34
  queue.close unless status.success?
35
35
  end
@@ -17,14 +17,6 @@ module NSWTopo
17
17
  end
18
18
 
19
19
  module Formats
20
- def neatline_path_data
21
- @neatline.coordinates.map do |ring|
22
- ring.map do |point|
23
- point.join(" ")
24
- end.join(" L ").prepend("M ").concat(" Z")
25
- end.join(" ")
26
- end
27
-
28
20
  def render_svg(svg_path, background:, **options)
29
21
  if uptodate?("map.svg", "map.yml")
30
22
  log_update "nswtopo: reading existing map SVG"
@@ -63,7 +55,7 @@ module NSWTopo
63
55
  # add defs for map filters and masks
64
56
  defs = svg.add_element("defs", "id" => "map.defs")
65
57
  defs.add_element("rect", "id" => "map.rect", "width" => width, "height" => height)
66
- defs.add_element("path", "id" => "map.neatline", "d" => neatline_path_data)
58
+ defs.add_element("path", "id" => "map.neatline", "d" => @neatline.svg_path_data)
67
59
  defs.add_element("clipPath", "id" => "map.clip").add_element("use", "href" => "#map.neatline")
68
60
 
69
61
  # add a filter converting alpha channel to cutout mask
@@ -78,8 +78,8 @@ module NSWTopo
78
78
  raster_info = "%i×%i (%.1fMpx) map raster at %s" % [*raster_size, megapixels, ppi_info]
79
79
  log_update "chrome: creating #{raster_info}"
80
80
 
81
- REXML::Document.new(svg_path.read).elements["svg/@viewBox"].value.split.map(&:to_f).last(2).map do |mm|
82
- (0...(mm / mm_per_px).ceil).step(TILE).map do |px|
81
+ raster_size.map do |px|
82
+ (0...px).step(TILE).map do |px|
83
83
  [px, px * mm_per_px]
84
84
  end
85
85
  end.inject(&:product).map(&:transpose).map do |raster_offset, viewport_offset|
@@ -30,7 +30,7 @@ module NSWTopo
30
30
 
31
31
  indexed_dem_path = temp_dir / "dem.#{index}.tif"
32
32
  OS.gdalbuildvrt "-overwrite", "-allow_projection_difference", "-a_srs", projection, "-input_file_list", txt_path, vrt_path
33
- OS.gdalwarp "-t_srs", @map.projection, "-tr", @mm_per_px, @mm_per_px, "-r", "bilinear", "-cutline", "GeoJSON:/vsistdin/", "-crop_to_cutline", vrt_path, indexed_dem_path do |stdin|
33
+ OS.gdalwarp "-t_srs", @map.projection, "-tr", @mm_per_px, @mm_per_px, "-r", "bilinear", "-cutline", "GeoJSON:/vsistdin?buffer_limit=-1", "-crop_to_cutline", vrt_path, indexed_dem_path do |stdin|
34
34
  stdin.puts cutline.to_json
35
35
  end
36
36
  indexed_dem_path
@@ -64,7 +64,7 @@ module NSWTopo
64
64
  end
65
65
 
66
66
  log_update "%s: smoothing DEM raster" % @name
67
- OS.gdal_translate "/vsistdin/", blur_path do |stdin|
67
+ OS.gdal_translate "/vsistdin?buffer_limit=-1", blur_path do |stdin|
68
68
  stdin.write xml
69
69
  end
70
70
  end
@@ -47,7 +47,7 @@ module NSWTopo
47
47
 
48
48
  def reproject_to(projection)
49
49
  return self if self.projection == projection
50
- json = OS.ogr2ogr "-t_srs", projection, "-f", "GeoJSON", "-lco", "RFC7946=NO", "/vsistdout/", "GeoJSON:/vsistdin/" do |stdin|
50
+ json = OS.ogr2ogr "-t_srs", projection, "-f", "GeoJSON", "-lco", "RFC7946=NO", "/vsistdout/", "GeoJSON:/vsistdin?buffer_limit=-1" do |stdin|
51
51
  stdin.puts to_json
52
52
  end
53
53
  Collection.load json, projection: projection
@@ -67,7 +67,7 @@ module NSWTopo
67
67
  end
68
68
 
69
69
  extend Forwardable
70
- delegate %i[coordinates properties wkt area] => :first
70
+ delegate %i[coordinates properties wkt area svg_path_data] => :first
71
71
  delegate %i[length] => :@features
72
72
 
73
73
  def to_json(**extras)
@@ -83,7 +83,7 @@ module NSWTopo
83
83
  end
84
84
 
85
85
  def with_sql(sql, name: @name)
86
- json = OS.ogr2ogr *%w[-f GeoJSON -lco RFC7946=NO /vsistdout/ GeoJSON:/vsistdin/ -dialect SQLite -sql], sql do |stdin|
86
+ json = OS.ogr2ogr *%w[-f GeoJSON -lco RFC7946=NO /vsistdout/ GeoJSON:/vsistdin?buffer_limit=-1 -dialect SQLite -sql], sql do |stdin|
87
87
  stdin.puts to_json
88
88
  end
89
89
  Collection.load(json, projection: @projection).with_name(name)
@@ -123,7 +123,7 @@ module NSWTopo
123
123
  end
124
124
 
125
125
  def clip(polygon)
126
- OS.ogr2ogr "-f", "GeoJSON", "-lco", "RFC7946=NO", "-clipsrc", polygon.wkt, "/vsistdout/", "GeoJSON:/vsistdin/" do |stdin|
126
+ OS.ogr2ogr "-f", "GeoJSON", "-lco", "RFC7946=NO", "-clipsrc", polygon.wkt, "/vsistdout/", "GeoJSON:/vsistdin?buffer_limit=-1" do |stdin|
127
127
  stdin.puts to_json
128
128
  end.then do |json|
129
129
  Collection.load json, projection: @projection
@@ -26,17 +26,15 @@ module NSWTopo
26
26
  end || lods.last
27
27
  tile_level, tile_resolution = lod.values_at "level", "resolution"
28
28
 
29
- target_bbox.coordinates.first.map do |corner|
30
- corner - origin
31
- end.transpose.map(&:minmax).zip(tile_sizes).map do |bound, tile_size|
32
- bound / tile_resolution / tile_size
29
+ target_bbox.bounds.zip(origin, tile_sizes).map do |(min, max), origin, tile_size|
30
+ [(min - origin) / tile_resolution / tile_size, (max - origin) / tile_resolution / tile_size]
33
31
  end.map do |min, max|
34
32
  (min.floor..max.ceil).each_cons(2).to_a
35
33
  end.inject(&:product).inject(GeoJSON::Collection.new(projection: service.projection)) do |tiles, (cols, rows)|
36
34
  [cols, rows].zip(tile_sizes).map do |indices, tile_size|
37
35
  indices.map { |index| index * tile_size * tile_resolution }
38
36
  end.transpose.map do |corner|
39
- corner + origin
37
+ corner.zip(origin).map(&:sum)
40
38
  end.transpose.then do |bounds|
41
39
  ring = bounds.inject(&:product).values_at(0,2,3,1,0)
42
40
  ullr = bounds.inject(&:product).values_at(1,2).flatten
@@ -42,7 +42,7 @@ module NSWTopo
42
42
  end
43
43
 
44
44
  def check_geos!
45
- json = OS.ogr2ogr "-dialect", "SQLite", "-sql", "SELECT geos_version() AS version", "-f", "GeoJSON", "-lco", "RFC7946=NO", "/vsistdout/", "/vsistdin/" do |stdin|
45
+ json = OS.ogr2ogr "-dialect", "SQLite", "-sql", "SELECT geos_version() AS version", "-f", "GeoJSON", "-lco", "RFC7946=NO", "/vsistdout/", "GeoJSON:/vsistdin?buffer_limit=-1" do |stdin|
46
46
  stdin.write GeoJSON::Collection.new.to_json
47
47
  end
48
48
  raise unless version = JSON.parse(json).dig("features", 0, "properties", "version")
@@ -107,7 +107,7 @@ module NSWTopo
107
107
  end
108
108
 
109
109
  contours.each_slice(100).inject(nil) do |update, features|
110
- OS.ogr2ogr "-a_srs", @map.projection, "-nln", "contour", *update, "-simplify", @simplify, *db_flags, db_path, "GeoJSON:/vsistdin/" do |stdin|
110
+ OS.ogr2ogr "-a_srs", @map.projection, "-nln", "contour", *update, "-simplify", @simplify, *db_flags, db_path, "GeoJSON:/vsistdin?buffer_limit=-1" do |stdin|
111
111
  stdin.write contours.with_features(features).to_json
112
112
  end
113
113
  %w[-update -append]
@@ -3,7 +3,7 @@ module NSWTopo
3
3
  using Helpers
4
4
  def create
5
5
  Dir.mktmppath do |temp_dir|
6
- args = ["-t_srs", @map.projection, "-r", "bilinear", "-cutline", "GeoJSON:/vsistdin/", "-te", *@map.te, "-of", "GTiff", "-co", "TILED=YES"]
6
+ args = ["-t_srs", @map.projection, "-r", "bilinear", "-cutline", "GeoJSON:/vsistdin?buffer_limit=-1", "-te", *@map.te, "-of", "GTiff", "-co", "TILED=YES"]
7
7
  args += ["-tr", @mm_per_px, @mm_per_px] if Numeric === @mm_per_px
8
8
  OS.gdalwarp *args, get_raster(temp_dir), "/vsistdout/" do |stdin|
9
9
  stdin.puts @map.cutline.to_json
@@ -31,7 +31,7 @@ module NSWTopo
31
31
  end.then do |(width, height), (_, mm_per_px, *)|
32
32
  image.add_attributes "width" => width, "height" => height, "transform" => "scale(#{mm_per_px})"
33
33
  end
34
- OS.gdal_translate "-of", "PNG", "-co", "ZLEVEL=9", "/vsistdin/", "/vsistdout/" do |stdin|
34
+ OS.gdal_translate "-of", "PNG", "-co", "ZLEVEL=9", "/vsistdin?buffer_limit=-1", "/vsistdout/" do |stdin|
35
35
  stdin.binmode.write tif
36
36
  end.then do |png|
37
37
  image.add_attributes "href" => "data:image/png;base64,#{Base64.encode64 png}", "image-rendering" => "optimizeQuality"
@@ -40,7 +40,7 @@ module NSWTopo
40
40
  end
41
41
 
42
42
  def to_s
43
- OS.gdalinfo "-json", "/vsistdin/" do |stdin|
43
+ OS.gdalinfo "-json", "/vsistdin?buffer_limit=-1" do |stdin|
44
44
  stdin.binmode.write @map.read(filename)
45
45
  end.then do |json|
46
46
  JSON.parse(json).values_at "size", "geoTransform"
@@ -50,7 +50,7 @@ module NSWTopo
50
50
  end.inject(&:merge)
51
51
 
52
52
  log_update "%s: calculating DEM" % @name
53
- OS.gdal_grid "-a", "linear:radius=0:nodata=-9999", "-zfield", "elevation", "-ot", "Float32", "-txe", *bounds[0], "-tye", *bounds[1], "-outsize", *outsize, "/vsistdin/", dem_path do |stdin|
53
+ OS.gdal_grid "-a", "linear:radius=0:nodata=-9999", "-zfield", "elevation", "-ot", "Float32", "-txe", *bounds[0], "-tye", *bounds[1], "-outsize", *outsize, "GeoJSON:/vsistdin?buffer_limit=-1", dem_path do |stdin|
54
54
  stdin.puts collection.to_json
55
55
  end
56
56
 
@@ -64,7 +64,7 @@ module NSWTopo
64
64
  begin
65
65
  log_update "%s: generating shaded relief" % @name
66
66
  OS.gdaldem *%W[hillshade -q -compute_edges -s #{@map.scale / 1000.0} -z #{@factor} -az #{@azimuth} -#{@method}], dem_path, raw_path
67
- OS.gdalwarp "-t_srs", @map.projection, "-cutline", "GeoJSON:/vsistdin/", "-crop_to_cutline", raw_path, tif_path do |stdin|
67
+ OS.gdalwarp "-t_srs", @map.projection, "-cutline", "GeoJSON:/vsistdin?buffer_limit=-1", "-crop_to_cutline", raw_path, tif_path do |stdin|
68
68
  stdin.puts cutline.to_json
69
69
  end
70
70
  rescue OS::Error
@@ -64,7 +64,7 @@ module NSWTopo
64
64
  tif_path = temp_dir / "source.tif"
65
65
  vrt_path = temp_dir / "source.vrt"
66
66
 
67
- args = ["-t_srs", @map.projection, "-r", "nearest", "-cutline", "GeoJSON:/vsistdin/", "-crop_to_cutline"]
67
+ args = ["-t_srs", @map.projection, "-r", "nearest", "-cutline", "GeoJSON:/vsistdin?buffer_limit=-1", "-crop_to_cutline"]
68
68
  args += ["-tr", @mm_per_px, @mm_per_px] if @mm_per_px
69
69
  OS.gdalwarp *args, *vrt_paths, tif_path do |stdin|
70
70
  stdin.puts @map.cutline.to_json
data/lib/nswtopo/map.rb CHANGED
@@ -16,12 +16,18 @@ module NSWTopo
16
16
  extend Forwardable
17
17
  delegate %i[write mtime read uptodate?] => :@archive
18
18
 
19
- def self.init(archive, scale: 25000, rotation: 0.0, bounds: nil, coords: nil, dimensions: nil, margins: nil, **neatline_options)
19
+ def self.init(archive, scale: 25000, rotation: 0.0, bounds: nil, coords: nil, neatline: nil, dimensions: nil, margins: nil, **neatline_options)
20
20
  points = case
21
21
  when dimensions && margins
22
22
  raise "can't specify both margins and map dimensions"
23
+ when dimensions && neatline
24
+ raise "can't specify both neatline and map dimensions"
25
+ when bounds && neatline
26
+ raise "can't specify both bounds and neatline"
27
+ when coords && neatline
28
+ raise "can't specify both neatline and map coordinates"
23
29
  when coords && bounds
24
- raise "can't specify both bounds file and map coordinates"
30
+ raise "can't specify both bounds and map coordinates"
25
31
  when coords
26
32
  GeoJSON.multipoint(coords)
27
33
  when bounds
@@ -29,6 +35,10 @@ module NSWTopo
29
35
  margins ||= [15, 15] unless dimensions || gps.polygons.any?
30
36
  raise "no features found in %s" % bounds if gps.none?
31
37
  end
38
+ when neatline
39
+ neatline = GPS.load(neatline)
40
+ raise "neatline must be a single polygon" unless neatline.polygon?
41
+ neatline
32
42
  else
33
43
  raise "no bounds file or map coordinates specified"
34
44
  end.dissolve_points
@@ -73,8 +83,12 @@ module NSWTopo
73
83
  raise "not enough information to calculate map size – check bounds file, or specify map dimensions or margins"
74
84
  end
75
85
 
76
- ring = [0, 0].zip(dimensions).inject(&:product).values_at(0,2,3,1,0)
77
- neatline = GeoJSON.polygon [ring], projection: projection, name: "neatline"
86
+ if neatline
87
+ neatline = neatline.reproject_to projection
88
+ else
89
+ ring = [0, 0].zip(dimensions).inject(&:product).values_at(0,2,3,1,0)
90
+ neatline = GeoJSON.polygon [ring], projection: projection, name: "neatline"
91
+ end
78
92
 
79
93
  neatline_options.each do |key, value|
80
94
  case key
@@ -24,6 +24,6 @@ module NSWTopo
24
24
  end
25
25
  end
26
26
 
27
- VERSION = Version["nswtopo 3.1"]
27
+ VERSION = Version["nswtopo 3.1.2"]
28
28
  MIN_VERSION = Version["nswtopo 3.0"]
29
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nswtopo
3
3
  version: !ruby/object:Gem::Version
4
- version: '3.1'
4
+ version: 3.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Hollingworth
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-04 00:00:00.000000000 Z
11
+ date: 2023-11-25 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -150,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
150
  - !ruby/object:Gem::Version
151
151
  version: '0'
152
152
  requirements:
153
- - GDAL >= v3.4
153
+ - GDAL >= v3.8
154
154
  - Google Chrome >= v112
155
155
  rubygems_version: 3.3.26
156
156
  signing_key: