0

Is there a tool or procedure on ArcMap 10.8 (similar to the Tom.bio plugin in QGIS) that allows the conversion of points with easting, northing and grid reference info into polygons of GB OS Grid references?

The points represent the locations of thousands of buildings and houses.

The tool/procedure should allow the conversion of points into different grid reference squares depending on the grid reference of the point (e.g. a point with NT36 should create a 10km square, a point with NT24B a 2km square, etc.).

4
  • Just use the shapefiles from "A collection of Ordnance Survey National Grids in Shapefile format" > github.com/charlesroper/OSGB_Grids/tree/master/Shapefile
    – Mapperz
    Commented Oct 6, 2020 at 15:44
  • Hi Mapperz, I think there was a bit of ambiguity in my question. I do not need a shapefile for the GB OS grid (I already have that!) but I just need to to convert the points (the location of several buildings) in polygons that will need to overlap GB OS Grid references at different resolutions. Commented Oct 7, 2020 at 17:13
  • In ArcGIS you can use the spatial join. desktop.arcgis.com/en/arcmap/latest/tools/analysis-toolbox/…
    – Mapperz
    Commented Oct 7, 2020 at 17:26
  • You could also create a thematic map with squares as map symbol using ground km dimensions instead of mm. Edit: don't know if that is only possible in QGIS...
    – Hans Erren
    Commented Oct 10, 2020 at 15:03

2 Answers 2

0

I needed an answer to this but couldn't find one, so put this together. Could probably be more elegant but seems to work. From an ARCGIS Pro Notebook, with 3 functions, one to convert the grid reference value into easting, northing and size; one for the special case of 2km tetrads; one to create the polygon and the main block to create the layer using cursors, which was largely based on the example provided in the link in the first line. Uses a point layer and creates a polygon layer with squares of different siz

    def GR_convert(GR):    # dummy value  SP123456
    
    LGR = len(GR)    # length of grid reference
    FGR = int(LGR/2) -1   # figures in easting/northing, e.g 3 for dummy
    PGR = 10**(5-FGR) # precision  - 100 for dummy
    GRnum2 = ord(GR[1]) - ord('A')    # position of 2nd letter in alphabet -1 (A=0, Z=25)
    if GRnum2 >= 8:                   # No I so subtracts 1 from J to Z 
        GRnum2 = GRnum2 - 1
    E1 = GRnum2 % 5  # calculates column 0:4 of letter
    N1 = 4 - (GRnum2//5)    # calculates row 0:4 of letter
    East_Num = int(GR[2:FGR+2])  # takes easting number
    North_Num = int(GR[FGR+2:2*FGR+2])   #takes northing number
    Easting = (E1*100000) + (East_Num * PGR) # calculates Easting
    Northing = (N1*100000) + (North_Num * PGR)  # calculates Northing.
    if GR[0] in ('T', 'O'):
        Easting += 500000
    if GR[0] in ('T', 'N'):
        Northing += 500000
    if GR[0] in ('H', 'J'):
        Northing += 1000000
    if LGR == 5 and GR[4].isalpha():
        e,n = tetrad(GR[4])
        Easting += e*2000
        Northing += n*2000
        PGR = 2000
    print(GR[1],GRnum2,LGR, FGR, PGR, E1, N1)
    return(Easting, Northing, PGR)

    def tetrad(tet_lett):
        tet_num = ord(tet_lett) - ord('A')    # position of 2nd letter in alphabet -1 (A=0, Z=25)
        if tet_num >= 14:                   # No O so subtracts 1 from P to Z 
            tet_num -= 1
        tet_N = (tet_num) % 5  # calculates row 0:4 of letter
        tet_E = (tet_num//5)    # calculates column 0:4 of letter
        return(tet_E, tet_N)

    def GR_square(gridref):
    East, North, Precision = GR_convert(gridref)
    SR = arcpy.SpatialReference(27700)
    corners = []
    corners.append(arcpy.Point(East, North))
    corners.append(arcpy.Point(East+Precision, North))
    corners.append(arcpy.Point(East+Precision, North+Precision))
    corners.append(arcpy.Point(East, North+Precision))
    corners.append(arcpy.Point(East, North))
    square = arcpy.Polygon(arcpy.Array(corners),SR)
    return square

# adapted from https://community.esri.com/t5/python-questions/python-script-create-a-rectangle-using-coordinates/td-p/235234

import os

arcpy.env.overwriteOutput = True

# input dbf file, edit this !!!
tbl = r'G:\Active contract work\P22-01 NWD AONB heathland project\2022\Maps\NWDspecies.gdb\TVrecords20220818_XYTableToPoint'

# edit these field names !!!
fld_oid_in = 'Occurrence_ID'
#field_list = [f.name for f in arcpy.ListFields(tbl)]
#print(field_list)
tax_gp = ''
sp_name = 'Scientific_name'
com_name = 'Common_name'
grid_ref = 'OSGR'
loc = 'Locality'
date = 'End_date'
abund = 'Abundance'
comment = 'Occurrence_remarks'
status = ''
source = 'NBNA'
list_fields  = (fld_oid_in, sp_name, com_name, grid_ref, loc, date, abund, comment) # add/remove according to source
#fld_oid_out = 'OID_DBF'

# output feature class   # edit this !!!
fc_out = r"G:\Active contract work\P22-01 NWD AONB heathland project\2022\Maps\NWDspecies.gdb\squares"

# define a spatial reference, edit this !!!
sr = arcpy.SpatialReference(27700)  # example for OSGB

# create output featureclass
fc_ws, fc_name = os.path.split(fc_out)
arcpy.CreateFeatureclass_management(fc_ws, fc_name, "POLYGON", None, None, None, sr)

# add output fields
arcpy.management.AddField(fc_out, 'Occurrence_ID', "TEXT", None)
arcpy.management.AddField(fc_out, 'Taxon_group', "TEXT", None)
arcpy.management.AddField(fc_out, 'Species_name', "TEXT", None)
arcpy.management.AddField(fc_out, 'Common_Name', "TEXT", None)
arcpy.management.AddField(fc_out, 'Grid_Ref', "TEXT", None)
arcpy.management.AddField(fc_out, 'Location', "TEXT", None)
arcpy.management.AddField(fc_out, 'Date', "TEXT", None)
arcpy.management.AddField(fc_out, 'Abundance', "TEXT", None)
arcpy.management.AddField(fc_out, 'Comment', "TEXT", None)
arcpy.management.AddField(fc_out, 'Status', "TEXT", None)
arcpy.management.AddField(fc_out, 'Source', "TEXT", None)


# insert cursor to store the results
flds_out = ('SHAPE@', fld_oid_in, 'Species_name', 'Common_Name', 'Grid_Ref', 'Location', 'Date', 'Abundance', 'Comment', 'Source')
with arcpy.da.InsertCursor(fc_out, flds_out) as curs_out:

    # loop over dbf file
        #flds = (grid_ref, fld_oid_in)
        with arcpy.da.SearchCursor(tbl, list_fields) as curs:
            for row in curs:
                oi = row[0]
                #tg = row[0]
                sn = row[1]
                cn = row[2]
                gr = row[3]
                lo = row[4]
                da = row[5]
                ab = row[6]
                co = row[7]
                #st = row[8]
                so = source
                
                Grid_square = GR_square(gr)

                curs_out.insertRow((Grid_square, oi, sn, cn, gr, lo, da, ab, co, so))            

0

An alternative approach to converting BNG into XY (or even lat/long) is the gridreferencefinder website. It has a useful online batch conversion tool. Simply copy and paste, no need for any code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.