0

I am trying to limit a large collection of UK OS Grid References (easting and northing) to only those that are in the mainland Great Britain.

-- Background on grid references --

The OS "National Grid" is formed of "easting"s and "northing"s relative to an origin (0,0). For our purposes, (700000, 1300000) is the theoretical maximum (top-right of the UK).

-- What I need, and what I've done so far --

I need to exclude any grid references that are not in mainland Great Britain (i.e. the largest island of the UK). I am happy for this to be a rough "best-guess" algorithm; but I definitely need something better than the whole range of values; which is kind of what I've got now.

The OS system splits the country into 100km squares, which is a start. This image shows how the UK is split up:

OS UK Grid References Map (By cmglee, Strebe, MansLaughter, Alexrk2 from naturalearthdata, Pethrus and nandhp - British National Grid.svgNorthwestern Europe on OSGB 1936 Datum.svg, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=35301574)

From that, given that each square (with two letters in) is one hundred thousand metres square, I know that I only need to consider eastings SW in the west to TG in the east (100000 to 700000) and northings in the approximate range SW..NC at the tallest point (0 to 999999) - which cuts down the numbers considerably; but there's still more to do.

What my logic so far has given me, therefore, is the rectangle SW..HW..JW..TW.

I know that, for each easting or range of eastings, I could store a map of valid northing values (and vice-versa) - and that would be one option for implementing this; however I was wondering if anyone had any other ideas. I am considering storing some kind of polygon that represents the UK, and then checking if the polygon contains the given point?

I'll be implementing in java, using integers for the easting and northing values.

My current crude method is therefore just a simple:

    public final static int minOSEasting = 100000;
    public final static int  minOSNorthing = 1;
    public final static int maxOSEasting = 700000;
    public final static int maxOSNorthing = 1000000;
    public static boolean isValid(int easting, int northing)
    {
        return (easting > minOSEasting && easting < maxOSEasting && northing > minOSNorthing && northing < maxOSNorthing);
    }

I would rather not use an external library or web service call.

--Edit-- see my answer (https://stackoverflow.com/a/56059697/318414) for the coordinates I used in the end

simonalexander2005
  • 4,338
  • 4
  • 48
  • 92

2 Answers2

1

Seems you just want a point in polygon algorithm. Try this one

Point in Polygon Algorithm

Jon Guiton
  • 1,360
  • 1
  • 9
  • 11
0

The answer by Jon Guiton got me looking in the right direction, to find the Java java.awt.Polygon class, which has a contains method that already implements an appropriate algorithm - so this is what I ended up using.

private static final Polygon greatBritain = new Polygon();

// initialisation for static objects
static 
{
    // All Points are approximate, outlining Great Britain without intersecting the mainland or IoW

    // across the south coast, west to east
    greatBritain.addPoint(170133,119);
    greatBritain.addPoint(203933,39504);
    greatBritain.addPoint(282096,32262);
    greatBritain.addPoint(324954,81140);
    greatBritain.addPoint(360590,61729);
    greatBritain.addPoint(567458,85461);
    greatBritain.addPoint(662279,148714);
    // up the east coast
    greatBritain.addPoint(623616,202459);
    greatBritain.addPoint(656468,255852);
    greatBritain.addPoint(660086,340187);
    greatBritain.addPoint(572388,351306);
    greatBritain.addPoint(545265,426094);
    greatBritain.addPoint(514388,498407);
    greatBritain.addPoint(464726,534376);
    greatBritain.addPoint(425395,632549);
    greatBritain.addPoint(362078,722471);
    greatBritain.addPoint(426485,846924);
    greatBritain.addPoint(392797,878940);
    greatBritain.addPoint(289069,872012);
    greatBritain.addPoint(341612,943508);
    greatBritain.addPoint(345483,978319);
    // across the north coast, east to west
    greatBritain.addPoint(213057,976098);
    greatBritain.addPoint(183952,903168);
    greatBritain.addPoint(138593,888094);
    greatBritain.addPoint(90959,827213);
    // down the west coast
    greatBritain.addPoint(165298,730796);
    greatBritain.addPoint(148429,620198);
    greatBritain.addPoint(191251,537703);
    greatBritain.addPoint(225538,523691);
    greatBritain.addPoint(271147,529579);
    greatBritain.addPoint(326709,448021);
    greatBritain.addPoint(320443,395657);
    greatBritain.addPoint(292079,380022);
    greatBritain.addPoint(247632,404665);
    greatBritain.addPoint(216638,387248);
    greatBritain.addPoint(222592,352210);
    greatBritain.addPoint(202125,322380);
    greatBritain.addPoint(244869,308001);
    greatBritain.addPoint(243211,278849);
    greatBritain.addPoint(179693,243828);
    greatBritain.addPoint(156928,205381);
    greatBritain.addPoint(265030,166546);
    greatBritain.addPoint(126856,27044);
}

public static boolean isValid(int easting, int northing)
{
    return greatBritain.contains(easting, northing);        
}
simonalexander2005
  • 4,338
  • 4
  • 48
  • 92