// 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 }
// 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 }
// serialize gets called by the respective handler methods to perform the serialization in the requested output representation func serialize(latlong *cartconvert.PolarCoord, oformat string) (interface{}, error) { var serializestruct interface{} var err error switch oformat { case OFlatlongdeg: lat, long := cartconvert.LatLongToString(latlong, cartconvert.LLFdms) serializestruct = &LatLong{Lat: lat, Long: long, Fmt: cartconvert.LLFdms.String(), LatLongString: latlong.String()} case OFlatlongcomma: lat, long := cartconvert.LatLongToString(latlong, cartconvert.LLFdeg) serializestruct = &LatLong{Lat: lat, Long: long, Fmt: cartconvert.LLFdeg.String(), LatLongString: latlong.String()} case OFgeohash: serializestruct = &GeoHash{GeoHash: cartconvert.LatLongToGeoHash(latlong)} case OFUTM: utm := cartconvert.LatLongToUTM(latlong) serializestruct = &UTMCoord{UTMCoord: utm, UTMString: utm.String()} case OFBMN: var bmnval *bmn.BMNCoord bmnval, err = bmn.WGS84LatLongToBMN(latlong, bmn.BMNZoneDet) if err == nil { serializestruct = &BMN{BMNCoord: bmnval, BMNString: bmnval.String()} } case OFOSGB: var osgb36val *osgb36.OSGB36Coord osgb36val, err = osgb36.WGS84LatLongToOSGB36(latlong) if err == nil { serializestruct = &OSGB36{OSGB36Coord: osgb36val, OSGB36String: osgb36val.String()} } default: err = fmt.Errorf("Unsupported output format: '%s'", oformat) } return serializestruct, err }
func main() { var ofcmdlinespec, ifcmdlinespec string var of displayformat var ifm inputformat var lines uint var instring, outstring, ofparamvalues, ifparamvalues string var pc *cartconvert.PolarCoord for key, _ := range ofOptions { ofparamvalues += fmt.Sprintf(" %s ", key) } for key, _ := range ifOptions { ifparamvalues += fmt.Sprintf(" %s ", key) } flag.StringVar(&ofcmdlinespec, "of", "deg", "specify output format. Possible values are: "+ofparamvalues) flag.StringVar(&ifcmdlinespec, "if", "osgb36", "specify input format. Possible values are: "+ifparamvalues) flag.Parse() of = ofOptions[strings.ToLower(ofcmdlinespec)] ifm = ifOptions[strings.ToLower(ifcmdlinespec)] reader := bufio.NewReaderSize(os.Stdin, 100) longline := false for data, prefix, err := reader.ReadLine(); err != io.EOF; data, prefix, err = reader.ReadLine() { if err != nil { fmt.Fprintf(os.Stderr, "conv %d: %s\n", lines, err) continue } if prefix { longline = true continue } if longline { longline = false continue } lines++ instring = strings.TrimSpace(string(data)) if len(instring) == 0 { continue } switch ifm { case ifbmn: bmncoord, err := bmn.ABMNToStruct(instring) if err != nil { fmt.Fprintf(os.Stderr, "BMN: error on line %d: %s\n", lines, err) continue } pc, err = bmn.BMNToWGS84LatLong(bmncoord) if err != nil { fmt.Fprintf(os.Stderr, "BMN: error on line %d: %s (BMN does not return a lat/long bearing)\n", lines, err) continue } case ifosgb36: osgb36coord, err := osgb36.AOSGB36ToStruct(instring, osgb36.OSGB36Auto) if err != nil { fmt.Fprintf(os.Stderr, "OSGB36: error on line %d: %s\n", lines, err) continue } pc = osgb36.OSGB36ToWGS84LatLong(osgb36coord) } switch of { case ofdeg: lat, long := cartconvert.LatLongToString(pc, cartconvert.LLFdeg) outstring = lat + ", " + long case ofdms: outstring = pc.String() case ofutm: outstring = cartconvert.LatLongToUTM(pc).String() case ofgeohash: outstring = cartconvert.LatLongToGeoHash(pc) default: fmt.Fprintln(os.Stderr, "Unrecognized output specifier") flag.Usage() fmt.Fprintf(os.Stderr, "possible values are: [%s]\n", ofparamvalues) fmt.Fprintln(os.Stderr, "]") os.Exit(2) } fmt.Fprintf(os.Stdout, "%s\n", outstring) } }