diff --git a/Convert.go b/Convert.go index 7bf0cbd..23d43b4 100644 --- a/Convert.go +++ b/Convert.go @@ -27,6 +27,7 @@ const ( WorldMercator = EPSG3395 EPSG3857 = 3857 WebMercator = EPSG3857 + EPSG4087 = 4087 ) // ensure only one person is updating our cache of converters at a time @@ -69,6 +70,7 @@ var conversions = map[EPSGCode]*conversion{} var projStrings = map[EPSGCode]string{ EPSG3395: "+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84", // TODO: support +units=m +no_defs EPSG3857: "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0", // TODO: support +units=m +nadgrids=@null +wktext +no_defs + EPSG4087: "+proj=eqc +lat_ts=0 +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84", } // newConversion creates a conversion object for the destination systems. If diff --git a/Convert_test.go b/Convert_test.go index a61dbda..c242dcd 100644 --- a/Convert_test.go +++ b/Convert_test.go @@ -53,6 +53,17 @@ var testcases = []testcase{ -8641240.37, 4697899.31, }, }, + { + dest: proj.EPSG4087, + expectedA: []float64{ + -14221.96, 5733772.09, + 261848.16, 5438693.39, + 1391089.10, 4664596.47, + }, + expectedB: []float64{ + -8641240.37, 4322963.96, + }, + }, } func TestConvert(t *testing.T) { diff --git a/gie/Gie.go b/gie/Gie.go index 389cc69..06ef032 100644 --- a/gie/Gie.go +++ b/gie/Gie.go @@ -25,6 +25,7 @@ var supportedProjections = []string{ "merc", "airy", "august", + "eqc", } // If the proj string has one of these keys, we won't execute the Command. diff --git a/operations/Eqc.go b/operations/Eqc.go new file mode 100644 index 0000000..a79fb4d --- /dev/null +++ b/operations/Eqc.go @@ -0,0 +1,78 @@ +package operations + +import ( + "math" + + "github.com/go-spatial/proj/core" + "github.com/go-spatial/proj/merror" +) + +func init() { + core.RegisterConvertLPToXY("eqc", + "Equidistant Cylindrical (Plate Carree)", + "\n\tCyl, Sph\n\tlat_ts=[, lat_0=0]", + NewEqc, + ) +} + +// Eqc implements core.IOperation and core.ConvertLPToXY +type Eqc struct { + core.Operation + rc float64 +} + +// NewEqc creates a new Plate Carree system +func NewEqc(system *core.System, desc *core.OperationDescription) (core.IConvertLPToXY, error) { + op := &Eqc{} + op.System = system + + err := op.eqcSetup(system) + if err != nil { + return nil, err + } + return op, nil +} + +// Forward goes forewards +func (op *Eqc) Forward(lp *core.CoordLP) (*core.CoordXY, error) { + return op.spheroidalForward(lp) +} + +// Inverse goes backwards +func (op *Eqc) Inverse(xy *core.CoordXY) (*core.CoordLP, error) { + return op.spheroidalReverse(xy) +} + +//--------------------------------------------------------------------- + +func (op *Eqc) spheroidalForward(lp *core.CoordLP) (*core.CoordXY, error) { /* Ellipsoidal, forward */ + xy := &core.CoordXY{X: 0.0, Y: 0.0} + + P := op.System + + xy.X = op.rc * lp.Lam + xy.Y = lp.Phi - P.Phi0 + return xy, nil +} + +func (op *Eqc) spheroidalReverse(xy *core.CoordXY) (*core.CoordLP, error) { /* Ellipsoidal, inverse */ + lp := &core.CoordLP{Lam: 0.0, Phi: 0.0} + + P := op.System + + lp.Lam = xy.X / op.rc + lp.Phi = xy.Y + P.Phi0 + return lp, nil +} + +func (op *Eqc) eqcSetup(sys *core.System) error { + ps := op.System.ProjString + + latts, _ := ps.GetAsFloat("lat_ts") + if math.Cos(latts) <= 0 { + return merror.New(merror.LatTSLargerThan90) + } + op.rc = math.Cos(latts) + + return nil +} diff --git a/operations/operations_test.go b/operations/operations_test.go index 972538b..c76dc1b 100644 --- a/operations/operations_test.go +++ b/operations/operations_test.go @@ -101,6 +101,22 @@ var testdata = []data{ fwd: [][]float64{ {2, 1, 223404.978180972, 111722.340289763}, }, + }, { + // builtins.gie:1104 + proj: "proj=eqc +a=6400000 +lat_1=0.5 +lat_2=2", + delta: 0.1 * 0.001, + fwd: [][]float64{ + {2, 1, 223402.144255274, 111701.072127637}, + {2, -1, 223402.144255274, -111701.072127637}, + {-2, 1, -223402.144255274, 111701.072127637}, + {-2, -1, -223402.144255274, -111701.072127637}, + }, + inv: [][]float64{ + {200, 100, 0.001790493, 0.000895247}, + {200, -100, 0.001790493, -0.000895247}, + {-200, 100, -0.001790493, 0.000895247}, + {-200, -100, -0.001790493, -0.000895247}, + }, }, } @@ -186,3 +202,16 @@ func BenchmarkConvertAiry(b *testing.B) { _, _ = op.Forward(input) } } + +func BenchmarkConvertEqc(b *testing.B) { + ps, _ := support.NewProjString("+proj=eqc +a=6400000 +lat_1=0.5 +lat_2=2") + _, opx, _ := core.NewSystem(ps) + op := opx.(core.IConvertLPToXY) + input := &core.CoordLP{Lam: support.DDToR(12.0), Phi: support.DDToR(55.0)} + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _, _ = op.Forward(input) + } +}