smo_os_bng_grids 0.1.0 → 0.1.1

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: 684430c7a6c5d3ef278e2665c6482f8e38d6ce93f390d2559bd04fddf6e19f32
4
- data.tar.gz: 457fc3149fc1488920365f45b7368587a7ace3b2498abe0599254a325ea5a7ee
3
+ metadata.gz: a7b84aefde3700b30bac415cfc3063b022e1784142f9b7b500f9f3aea97c2e41
4
+ data.tar.gz: db5b6cf873e9d6f267997734544951fcc3f58db1533cba908aef4dbd4bd6a9b1
5
5
  SHA512:
6
- metadata.gz: e202eea264d08736074bf8783d135382e8107045d12d163a0db6d6ac8a58c478e526c6a9baf19da0ec825d2bd37b68a36edcb49279f2ad9d53b8487db3f97de7
7
- data.tar.gz: a936a88d9bedfb7efa63c74d4d56828f85c6a90202f9d8eaf23caa8ff8bb12490c4610b0b3314a2cb351a6ba959358676a83f00d17065a4ccc1b10c24764f7cd
6
+ metadata.gz: 10aea651302aad06011352d8f0f250c5ceb86ce6a0abcbf9584e793c66045e3596560a85b9c637aa1bf67b2c81addf29ff2b4acb2beebd57cb0353c22b06d3df
7
+ data.tar.gz: 1ac8d3f6d4a0ea8f9ad9f7b991e3acc45c9b87a62ddff4a3805cdb1a77bb22a74aeb3676f0a066e14d159789486f6a5e07bd9d42c116e6ad44dcb9aff299ec0b
data/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-05-04
11
+
12
+ ### Added
13
+ - `SmoOsBngGrids::Grid` for point-to-grid-ref lookup, bounds retrieval, and validation
14
+ - `SmoOsBngGrids::Lister` for listing, filtering, and spatial search of grid squares
15
+ - `SmoOsBngGrids::ShapefileWriter` for ESRI Shapefile export
16
+ - Support for 100km, 50km, 10km, 5km, and 1km resolutions
17
+ - Hardcoded geometry sourced from OS BNG Grids GeoPackage
18
+ - Circular radius and bounding box spatial search
19
+ - Test suite covering data loading, geometry, and bounds
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Open Government Licence v3.0
2
+
3
+ Copyright (c) 2026 Sebastian Madrid Ontiveros
4
+
5
+ Contains OS data. Crown copyright and database right 2026.
6
+
7
+ Licensed under the Open Government Licence v3.0.
8
+ https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/
9
+
10
+ You are free to copy, publish, distribute, transmit, adapt and exploit the
11
+ information commercially or non-commercially, provided you acknowledge the
12
+ source by including the following attribution statement:
13
+
14
+ Contains OS data. Crown copyright and database right 2026.
15
+
16
+ The Ordnance Survey grid data included in this gem is sourced directly from
17
+ the OS BNG Grids GeoPackage published by Ordnance Survey under the Open
18
+ Government Licence v3.0.
data/README.md ADDED
@@ -0,0 +1,208 @@
1
+ # smo_os_bng_grids
2
+
3
+ Pure Ruby gem for working with **Ordnance Survey British National Grid (BNG)** squares.
4
+ Point lookup, spatial search, bounds, corner coordinates, and Shapefile export — no external dependencies.
5
+
6
+ Developed by **Sebastian Madrid Ontiveros**.
7
+ Contains OS data. Crown copyright and database right 2025.
8
+ Licensed under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/).
9
+
10
+ [![Gem Version](https://badge.fury.io/rb/smo_os_bng_grids.svg)](https://badge.fury.io/rb/smo_os_bng_grids)
11
+
12
+ ---
13
+
14
+ ## Features
15
+
16
+ - **Hardcoded geometry** sourced directly from the OS BNG Grids GeoPackage (EPSG:27700)
17
+ - Grid squares at **100km, 50km, 10km, 5km, and 1km** resolutions (910,091 squares total)
18
+ - **Point lookup** — find the grid ref containing any easting/northing at any resolution
19
+ - **Spatial search** — find all tiles intersecting a radius or bounding box around a point
20
+ - **Bounds** — retrieve min/max easting/northing for any grid ref
21
+ - **Corner points** — NW → NE → SE → SW → NW, ready for InfoWorks ICM `boundary_array`
22
+ - **Shapefile export** — pure Ruby SHP/SHX/DBF/PRJ writer, no GDAL required
23
+ - **Pure Ruby stdlib only** — works in InfoWorks ICM 2027 embedded Ruby
24
+
25
+ ---
26
+
27
+ ## Installation
28
+
29
+ ```ruby
30
+ gem "smo_os_bng_grids"
31
+ ```
32
+
33
+ Or install directly:
34
+
35
+ ```bash
36
+ gem install smo_os_bng_grids
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Quick start
42
+
43
+ ```ruby
44
+ require "smo_os_bng_grids"
45
+
46
+ lister = SmoOsBngGrids::Lister.new
47
+
48
+ # Point lookup — what grid square is Edinburgh city centre in?
49
+ easting = 325000
50
+ northing = 673000
51
+
52
+ SmoOsBngGrids::Grid.ref_at(easting, northing, resolution: "10km") # => "NT27"
53
+ SmoOsBngGrids::Grid.ref_at(easting, northing, resolution: "1km") # => "NT2573"
54
+
55
+ # All resolutions at once
56
+ lister.find(easting, northing)
57
+ # => {"100km"=>"NT", "50km"=>"NTNW", "10km"=>"NT27", "5km"=>"NT27SE", "1km"=>"NT2573"}
58
+
59
+ # Bounds of a grid square
60
+ SmoOsBngGrids::Grid.bounds("NT27")
61
+ # => {min_e: 320000, min_n: 670000, max_e: 330000, max_n: 680000}
62
+ ```
63
+
64
+ ---
65
+
66
+ ## Grid resolutions
67
+
68
+ | Resolution | Count | Example ref | Square size |
69
+ |-----------|--------|-------------|-----------------|
70
+ | 100km | 91 | `NT` | 100km × 100km |
71
+ | 50km | 364 | `NTNW` | 50km × 50km |
72
+ | 10km | 9,100 | `NT27` | 10km × 10km |
73
+ | 5km | 36,400 | `NT27SE` | 5km × 5km |
74
+ | 1km | 910,000| `NT2573` | 1km × 1km |
75
+
76
+ ---
77
+
78
+ ## Listing grid squares
79
+
80
+ ```ruby
81
+ lister = SmoOsBngGrids::Lister.new
82
+
83
+ # All 100km squares
84
+ lister.list("100km")
85
+
86
+ # All 10km squares within NT
87
+ lister.list("10km", within: "NT")
88
+
89
+ # All 1km squares within NT27
90
+ lister.list("1km", within: "NT27")
91
+ ```
92
+
93
+ Each entry is a Hash:
94
+
95
+ ```ruby
96
+ {
97
+ ref: "NT27",
98
+ min_e: 320000, min_n: 670000,
99
+ max_e: 330000, max_n: 680000,
100
+ points: [
101
+ [320000, 680000], # NW
102
+ [330000, 680000], # NE
103
+ [330000, 670000], # SE
104
+ [320000, 670000], # SW
105
+ [320000, 680000] # NW (closed)
106
+ ]
107
+ }
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Spatial search
113
+
114
+ Find all tiles intersecting a radius or bounding box around a point:
115
+
116
+ ```ruby
117
+ lister = SmoOsBngGrids::Lister.new
118
+
119
+ # All 10km tiles within 12km of Edinburgh
120
+ tiles = lister.search(325000, 673000, resolution: "10km", radius: 12000)
121
+ tiles.each { |t| puts "#{t[:ref]} #{t[:distance_m]} m" }
122
+
123
+ # All 1km tiles within 1.5km of Edinburgh
124
+ lister.search(325000, 673000, resolution: "1km", radius: 1500)
125
+
126
+ # All 5km tiles within a 15km box around Edinburgh
127
+ lister.search(325000, 673000, resolution: "5km", box: 15000)
128
+ ```
129
+
130
+ Radius search also returns `:distance_m` — `0.0` when the point is inside the tile.
131
+
132
+ ---
133
+
134
+ ## Corner points — InfoWorks ICM
135
+
136
+ Every entry returned by `list`, `search`, and `entry_for` includes a `:points` array in **NW → NE → SE → SW → NW** order, matching the InfoWorks ICM `boundary_array` convention:
137
+
138
+ ```ruby
139
+ lister = SmoOsBngGrids::Lister.new
140
+
141
+ # Single tile containing a point
142
+ tile = lister.search(325000, 673000, resolution: "10km", radius: 1).first
143
+ boundary_array = tile[:points]
144
+ # => [[320000, 680000], [330000, 680000], [330000, 670000], [320000, 670000], [320000, 680000]]
145
+
146
+ # Flat XY array if needed
147
+ flat_xy = tile[:points].flatten
148
+ # => [320000, 680000, 330000, 680000, 330000, 670000, 320000, 670000, 320000, 680000]
149
+
150
+ # Convert a ref string to a full entry
151
+ entry = lister.entry_for("NT27SE")
152
+ entry[:points] # => [[325000, 675000], [330000, 675000], [330000, 670000], [325000, 670000], [325000, 675000]]
153
+ ```
154
+
155
+ ---
156
+
157
+ ## Shapefile export
158
+
159
+ Export any set of entries to ESRI Shapefile format (OSGB36 / EPSG:27700).
160
+ Pure Ruby — no GDAL, no external gems, works in InfoWorks ICM 2027.
161
+
162
+ ```ruby
163
+ lister = SmoOsBngGrids::Lister.new
164
+ writer = SmoOsBngGrids::ShapefileWriter.new
165
+
166
+ # From list()
167
+ writer.write(lister.list("10km", within: "NT"), "/tmp/nt_10km")
168
+
169
+ # From search()
170
+ entries = lister.search(325000, 673000, resolution: "10km", radius: 20000)
171
+ writer.write(entries, "/tmp/edinburgh_10km_20km")
172
+
173
+ # From find() — one tile per resolution
174
+ found = lister.find(325000, 673000)
175
+ found.each do |res, ref|
176
+ writer.write([lister.entry_for(ref)], "/tmp/edinburgh_#{res}")
177
+ end
178
+ ```
179
+
180
+ Produces `.shp`, `.shx`, `.dbf`, `.prj` — open directly in QGIS or ArcGIS.
181
+
182
+ ---
183
+
184
+ ## Grid reference validation
185
+
186
+ ```ruby
187
+ SmoOsBngGrids::Grid.valid?("NT") # => true
188
+ SmoOsBngGrids::Grid.valid?("NT27") # => true
189
+ SmoOsBngGrids::Grid.valid?("NT2573") # => true
190
+ SmoOsBngGrids::Grid.valid?("ZZ") # => false
191
+ ```
192
+
193
+ ---
194
+
195
+ ## Data
196
+
197
+ All geometry is hardcoded from the **OS BNG Grids GeoPackage** published by Ordnance Survey.
198
+ Source: [github.com/OrdnanceSurvey/osbng-grids](https://github.com/OrdnanceSurvey/osbng-grids)
199
+
200
+ Contains OS data. Crown copyright and database right 2025.
201
+ Licensed under the Open Government Licence v3.0.
202
+
203
+ ---
204
+
205
+ ## Attribution
206
+
207
+ Built by **Sebastian Madrid Ontiveros** to support hydraulic modelling and flood risk workflows in the UK.
208
+ If this gem saves you time, consider [buying Sebastian a coffee](https://buymeacoffee.com/smadrid).
@@ -32,6 +32,9 @@ module SmoOsBngGrids
32
32
 
33
33
  QUADRANTS = %w[SW SE NW NE].freeze
34
34
 
35
+ MSG_INVALID_RESOLUTION = "Unknown resolution %s. Valid: #{VALID_RESOLUTIONS.join(', ')}"
36
+ MSG_PROVIDE_RADIUS_OR_BOX = "Provide radius: or box: (not both)"
37
+
35
38
  # Quadrant offsets [easting_offset, northing_offset] from parent SW corner.
36
39
  QUADRANT_OFFSETS = {
37
40
  "SW" => [0, 0],
@@ -162,7 +162,7 @@ module SmoOsBngGrids
162
162
  def self.validate_resolution!(res)
163
163
  return if VALID_RESOLUTIONS.include?(res)
164
164
 
165
- raise ArgumentError, "Unknown resolution #{res.inspect}. Valid: #{VALID_RESOLUTIONS.join(', ')}"
165
+ raise ArgumentError, format(MSG_INVALID_RESOLUTION, res.inspect)
166
166
  end
167
167
 
168
168
  def self.validate_coords!(easting, northing)
@@ -33,8 +33,8 @@ module SmoOsBngGrids
33
33
  # @return [Array<Hash>] matching entries, each with :ref, :min_e, :min_n,
34
34
  # :max_e, :max_n, :points, :distance_m (circle only)
35
35
  def search(easting, northing, resolution: "10km", radius: nil, box: nil)
36
- raise ArgumentError, "Provide radius: or box: (not both)" if radius.nil? && box.nil?
37
- raise ArgumentError, "Provide radius: or box: (not both)" if radius && box
36
+ raise ArgumentError, MSG_PROVIDE_RADIUS_OR_BOX if radius.nil? && box.nil?
37
+ raise ArgumentError, MSG_PROVIDE_RADIUS_OR_BOX if radius && box
38
38
 
39
39
  Grid.validate_coords!(easting, northing)
40
40
  validate_resolution!(resolution)
@@ -153,7 +153,7 @@ module SmoOsBngGrids
153
153
  def validate_resolution!(res)
154
154
  return if VALID_RESOLUTIONS.include?(res)
155
155
 
156
- raise ArgumentError, "Unknown resolution #{res.inspect}. Valid: #{VALID_RESOLUTIONS.join(', ')}"
156
+ raise ArgumentError, format(MSG_INVALID_RESOLUTION, res.inspect)
157
157
  end
158
158
  end
159
159
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SmoOsBngGrids
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smo_os_bng_grids
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Madrid Ontiveros
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-05-04 00:00:00.000000000 Z
10
+ date: 2026-06-10 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: |
13
13
  Developed by Sebastian Madrid Ontiveros. Pure Ruby gem providing all Ordnance Survey
@@ -20,11 +20,15 @@ description: |
20
20
  Built to support hydraulic modelling and flood risk workflows in the UK.
21
21
  If this gem saves you time, consider buying Sebastian a coffee at
22
22
  https://buymeacoffee.com/smadrid
23
- email: []
23
+ email:
24
+ - sebasmadrid20@hotmail.com
24
25
  executables: []
25
26
  extensions: []
26
27
  extra_rdoc_files: []
27
28
  files:
29
+ - CHANGELOG.md
30
+ - LICENSE
31
+ - README.md
28
32
  - lib/smo_os_bng_grids.rb
29
33
  - lib/smo_os_bng_grids/constants.rb
30
34
  - lib/smo_os_bng_grids/data/grid_100km.rb