nswtopo 3.1 → 3.1.2

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 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: