// Transform a Swiss coordinate value to a GRS80 based latitude and longitude coordinate. Function returns // cartconvert.ErrRange, if the swiss coordinate type is not one of LV03 or LV95 func SwissCoordToGRS80LatLong(coord *SwissCoord) (*cartconvert.PolarCoord, error) { var fn, fe float64 switch coord.CoordType { case LV03: fe = 600000 fn = 200000 case LV95: fe = -2600000 fn = -1200000 default: return nil, cartconvert.ErrRange } gc := cartconvert.InverseTransverseMercator( &cartconvert.GeoPoint{Y: coord.Northing, X: coord.Easting, El: coord.El}, 46.952406, // lat0 7.439583, // long0 1, fe, // fe fn) // fn cart := cartconvert.PolarToCartesian(gc) // According to literature, the Granit87 parameters shall not be used in favour of // higher accuracy of the following shift values // pt := cartconvert.HelmertLV03ToWGS84Granit87.Transform(&cartconvert.Point3D{X: cart.X, Y: cart.Y, Z: cart.Z}) pt := &cartconvert.Point3D{X: cart.X + 674.374, Y: cart.Y + 15.056, Z: cart.Z + 405.346} return cartconvert.CartesianToPolar(&cartconvert.CartPoint{X: pt.X, Y: pt.Y, Z: pt.Z, El: cartconvert.GRS80Ellipsoid}), nil }
// Transform a BMN coordinate value to a WGS84 based latitude and longitude coordinate. Function returns // cartconvert.ErrRange, if the meridian stripe of the bmn-coordinate is not set func BMNToWGS84LatLong(bmncoord *BMNCoord) (*cartconvert.PolarCoord, error) { var long0, fe float64 switch bmncoord.Meridian { case BMNM28: long0 = 10.0 + 20.0/60.0 fe = 150000 case BMNM31: long0 = 13.0 + 20.0/60.0 fe = 450000 case BMNM34: long0 = 16.0 + 20.0/60.0 fe = 750000 default: return nil, cartconvert.ErrRange } gc := cartconvert.InverseTransverseMercator( &cartconvert.GeoPoint{Y: bmncoord.Height, X: bmncoord.Right, El: bmncoord.El}, 0, long0, 1, fe, -5000000) cart := cartconvert.PolarToCartesian(gc) pt := cartconvert.HelmertWGS84ToMGI.InverseTransform(&cartconvert.Point3D{X: cart.X, Y: cart.Y, Z: cart.Z}) return cartconvert.CartesianToPolar(&cartconvert.CartPoint{X: pt.X, Y: pt.Y, Z: pt.Z, El: cartconvert.WGS84Ellipsoid}), nil }
// Transform a latitude / longitude coordinate datum into a BMN coordinate. Function returns // cartconvert.ErrRange, if the meridian stripe of the bmn-coordinate is not set. // // Important: The reference ellipsoid of the originating coordinate system will be assumed // to be the WGS84Ellipsoid and will be set thereupon, regardless of the actually set reference ellipsoid. func WGS84LatLongToBMN(gc *cartconvert.PolarCoord, meridian BMNMeridian) (*BMNCoord, error) { var long0, fe float64 // This sets the Ellipsoid to WGS84, regardless of the actual value set gc.El = cartconvert.WGS84Ellipsoid cart := cartconvert.PolarToCartesian(gc) pt := cartconvert.HelmertWGS84ToMGI.Transform(&cartconvert.Point3D{X: cart.X, Y: cart.Y, Z: cart.Z}) polar := cartconvert.CartesianToPolar(&cartconvert.CartPoint{X: pt.X, Y: pt.Y, Z: pt.Z, El: cartconvert.Bessel1841MGIEllipsoid}) // Determine meridian stripe based on longitude if meridian == BMNZoneDet { switch { case 11.0+0.5/6*10 >= polar.Longitude && polar.Longitude >= 8.0+0.5/6*10: meridian = BMNM28 case 14.0+0.5/6*10 >= polar.Longitude && polar.Longitude >= 11.0+0.5/6*10: meridian = BMNM31 case 17.0+0.5/6*10 >= polar.Longitude && polar.Longitude >= 14.0+0.5/6*10: meridian = BMNM34 } } switch meridian { case BMNM28: long0 = 10.0 + 20.0/60.0 fe = 150000 case BMNM31: long0 = 13.0 + 20.0/60.0 fe = 450000 case BMNM34: long0 = 16.0 + 20.0/60.0 fe = 750000 default: return nil, cartconvert.ErrRange } gp := cartconvert.DirectTransverseMercator( polar, 0, long0, 1, fe, -5000000) return &BMNCoord{Meridian: meridian, Height: gp.Y, Right: gp.X, El: gp.El}, nil }
// Convert an OSGB36 coordinate value to a WGS84 based latitude and longitude coordinate. // // Important: A OSGB36 datum like NN11 will be internally expanded to NN1500015000 to point to the middle of the zone. // For the point at NN1000010000 it is necessary to fully qualify northing and easting. // // Plain grid zone specifiers will NOT be shifted towards the middle of the square. func OSGB36ToWGS84LatLong(coord *OSGB36Coord) *cartconvert.PolarCoord { easting, northing := OSGB36ZoneToRefCoords(coord) gc := cartconvert.InverseTransverseMercator( &cartconvert.GeoPoint{Y: float64(northing), X: float64(easting), El: coord.El}, 49, -2, 0.9996012717, 400000, -100000) cart := cartconvert.PolarToCartesian(gc) pt := cartconvert.HelmertWGS84ToOSGB36.InverseTransform(&cartconvert.Point3D{X: cart.X, Y: cart.Y, Z: cart.Z}) return cartconvert.CartesianToPolar(&cartconvert.CartPoint{X: pt.X, Y: pt.Y, Z: pt.Z, El: cartconvert.WGS84Ellipsoid}) }
// Transform a latitude / longitude coordinate datum into a OSGB36 coordinate. // // Important: The reference ellipsoid of the originating coordinate system will be assumed // to be the WGS84Ellipsoid and will be set thereupon, regardless of the actually set reference ellipsoid. func WGS84LatLongToOSGB36(gc *cartconvert.PolarCoord) (*OSGB36Coord, error) { // This sets the Ellipsoid to WGS84, regardless of the actual value set gc.El = cartconvert.WGS84Ellipsoid cart := cartconvert.PolarToCartesian(gc) pt := cartconvert.HelmertWGS84ToOSGB36.Transform(&cartconvert.Point3D{X: cart.X, Y: cart.Y, Z: cart.Z}) polar := cartconvert.CartesianToPolar(&cartconvert.CartPoint{X: pt.X, Y: pt.Y, Z: pt.Z, El: cartconvert.Airy1830Ellipsoid}) gp := cartconvert.DirectTransverseMercator( polar, 49, -2, 0.9996012717, 400000, -100000) return GridRefNumToLet(uint(gp.X+0.5), uint(gp.Y+0.5), 0, OSGB36_Max) }
// Transform a latitude / longitude coordinate datum into a Swiss coordinate. Function returns // cartconvert.ErrRange, if the coordinate type is not set. // // Important: The reference ellipsoid of the originating coordinate system will be assumed // to be the GRS80Ellipsoid and will be set thereupon, regardless of the actually set reference ellipsoid. func GRS80LatLongToSwissCoord(gc *cartconvert.PolarCoord, coordType SwissCoordType) (*SwissCoord, error) { var fn, fe float64 // This sets the Ellipsoid to GRS80, regardless of the actual value set gc.El = cartconvert.GRS80Ellipsoid cart := cartconvert.PolarToCartesian(gc) // According to literature, the Granit87 parameters shall not be used in favour of // higher accuracy of the following shift values // pt := cartconvert.HelmertWGS84ToMGI.Transform(&cartconvert.Point3D{X: cart.X, Y: cart.Y, Z: cart.Z}) pt := &cartconvert.Point3D{X: cart.X - 674.374, Y: cart.Y - 15.056, Z: cart.Z - 405.346} polar := cartconvert.CartesianToPolar(&cartconvert.CartPoint{X: pt.X, Y: pt.Y, Z: pt.Z, El: cartconvert.Bessel1841Ellipsoid}) switch coordType { case LV03: fe = 600000 fn = 200000 case LV95: fe = -2600000 fn = -1200000 default: return nil, cartconvert.ErrRange } gp := cartconvert.DirectTransverseMercator( polar, 46.952406, // lat0 7.439583, // long0 1, fe, // fe fn) // fn return &SwissCoord{CoordType: coordType, Northing: gp.Y, Easting: gp.X, El: gp.El}, nil }