Giter Club home page Giter Club logo

proj's Introduction

Build Status Report Card Coverage Status Godoc license

proj: PROJ4, for Go!

Proj is a selective and on-going port of the venerable PROJ.4 project to the Go language.

We do not intend to port all of PROJ.4: there is stuff in PROJ.4 that we'll probably never have a sufficient justification for bringing over. Likewise, we do not intend to do a verbatim port of the original code: naively translated C code doesn't make for maintainable (or idiomatic) Go code.

Installation

To install the packages, preparatory to using them in your own code:

go get -U github.com/go-spatial/proj

To copy the repo, preparatory to doing development:

git clone https://github.com/go-spatial/proj go test ./...

See below for API usage instructions.

Guiding Principles and Goals and Plans

In no particular order, these are the conditions we're imposing on ourselves:

  • We are going to use the PROJ 5.0.1 release as our starting point.
  • We will look to the proj4js project for suggestions as to what PROJ4 code does and does not need to be ported, and how.
  • We will consider numerical results returned by PROJ.4 to be "truth" (within appropriate tolerances).
  • We will try to port the "mathy" parts with close to a 1:1 correspondence, so as to avoid inadvertently damaging the algoirthms.
  • The "infrastructure" parts, however, such as proj string parsing and the coordinate system classes -- I'm looking at you, PJ -- will be generally rewritten in idiomatic Go.
  • The proj command-line app will not be fully ported. Instead, we will provide a much simpler tool.
  • All code will pass muster with the various Go linting and formatting tools.
  • Unit tests will be implemented for pretty much everything, using the "side-by-side" _test package style. Even without testing all error return paths, but we expect to reach about 80% coverage.
  • We will not port PROJ.4's new gie test harness directly; we will do a rewrite of a subset of it's features instead. The Go version fo gie should nonetheless be able to parse all of PROJ.4's supplied .gie files.
  • Go-style source code documentation will be provided.
  • A set of small, clean usage examples will be provided.

The APIs

There are two APIs at present, helpfully known as "the conversion API" and "the core API".

The Conversion API

This API is intended to be a dead-simple way to do a 2D projection from 4326. That is:

You Have: a point which uses two float64 numbers to represent lon/lat degrees in an epsg:4326 coordinate reference system

You Want: a point which uses two float64 numbers to represent meters in a projected coordinate system such as "web mercator" (epsg:3857).

If that's what you need to do, then just do this:

	var lonlat = []float64{77.625583, 38.833846}

	xy, err := proj.Convert(proj.EPSG3395, lonlat)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%.2f, %.2f\n", xy[0], xy[1])

Note that the lonlat array can contain more than two elements, so that you can project a whole set of points at once.

This API is stable and unlikely to change much. If the projected EPSG code you need is not supported, just let us know.

The Core API

Beneath the Conversion API, in the core package, lies the real API. With this API, you can provide a proj string (+proj=utm +zone=32...) and get back in return a coordinate system object and access to functions that perform forward and inverse operations (transformations or conversions).

The Core API is a work in progress. Only a subset of the full PROJ.4 operations are currently supported, and the structs and interfaces can be expected to evolve as we climb the hill to support more proj string keys, more projections, grid shifts, .def files, and so on.

For examples of how to sue the Core API, see the implementation of proj.Convert (in Convert.go) or the sample app in cmd/proj.

The Packages

The proj repo contains these packages (directories):

  • proj (top-level): the Conversion API
  • proj/cmd/proj: the simple proj command-line tool
  • proj/core: the Core API, representing coordinate systems and conversion operations
  • proj/gie: a naive implementation of the PROJ.4 gie tool, plus the full set of PROJ.4 test case files
  • proj/merror: a little error package
  • proj/mlog: a little logging package
  • proj/operations: the actual coordinate operations; these routines tend to be closest to the original C code
  • proj/support: misc structs and functions in support of the core package

Most of the packages have _test.go files that demonstrate how the various types and functions are (intended to be) used.

Future Work

We need to support grid shifts, turn on more proj string keys, make the Ellipse and Datum types be more independent, port a zillion different projection formulae, the icky operation typing needs to be rethought, and on and on. Such future work on proj will likely be driven by what coordinate systems and operations people need to be supported: someone will provide a proj string that leads to successful numerical outputs in PROJ.4 but dies in proj.

We welcome your participation! See CONTRIBUTING.md and/or contact [email protected] if you'd like to help out on the project.

proj's People

Contributors

meilinger avatar mpgerlek avatar prl900 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

proj's Issues

Proj command

As a simple example if nothing else, the proj command needs to be finished.

  • -inverse - optional, runs backwards
  • -verbose - optional, controls logging
  • -epsg NNNN - optional, instead of proj string
  • ...proj string... - default

Benchmark against C

We need to run something like the UTM example case over a zillion points, and see how it compares to the C code.

Awesome work!!!

Just wanted to let you know that this is awesome :) After having to spend an entire day looking into how to convert from WSG84 to UTM32 N Datum 50 natively, I have realized how much this tool is missing in the go eco system. I would love to help if I can, I am however no expert at all in proj4 or geo mappings in general...

Thank you for putting time into this :)

Add support for lcc projection.

When trying to use the following projection string:

+proj=lcc +lat_1=47.5 +lat_2=48.73333333333333 +lat_0=47 +lon_0=-120.8333333333333 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs

The currently does not support "+proj=lcc"

It would be greate to add that aglo to the system.

I think it is a bug

In the souce code of "core/System.go", line of 404, like "from = 1.0 / sys.FromMeter". I think it is a bug.
The right code maybe is: "from = 1.0 / to".

API design discussion

discussion moved here from go-spatial/tegola#267 (comment)

@ARolek suggests we hard-code a table of SRIDs and their corresponding proj strings

This is totally do-able. Taken one step more, and hiding the proj strings from the user, we can provide a set conversions from a geodetic lon/lat of degrees (e.g. 4326) system to a projected system of meters (e.g. 3395). Your suggested function works for this: proj.Project(from, to uint, point []float64) ([]float64, error). We will call this Use Case One.

However, proj can do way more stuff than that. It supports 3D coordinate systems, grid files, inverse conversions, complete transforms, and more that I only vaguely can appreciate (like you, I've just been a passive user of proj all these years).

/ping @jj0hns0n

So the question on the table is, do we really care about that other stuff? The safest answer is usually "eventually, maybe". That means we don't refactor the core code to support "only Use Case One and never anything else"; instead, we leave the core in a state where it can later be extended as we need to, and add a specialized Use Case One API on top of that core.

And indeed, timing-wise and functionality-wise, the core is in a pretty good place to start doing that right now. It makes sense.

@ARolek goes on to wonder about "automatically generating" code from proj strings

Well, yes-and-no.

You first parse the proj string to understand what sort of conversion (or other beast) is desired, along with the starting datum and ellipse and such. That information tells you how to create the System object (called PJ in the C code) and which algorithm needs to be run on that system. My code doesn't look at all like the C code anymore, except for the key mathematical fields in the objects.

However, those original algorithms are the parts of proj.4 that we want to change as little as possible. That code is where the hardcore math is, and in order to be able to carry over bug fixes (or add new projections) we need to keep the code relatively 1:1 with the C.

That said, a lot of the original C code is sort of table-driven in how things get created, and we've kept that model in the new Go code.

I need register more epsg code and string?

In the source of "Convert.go", the default epsg codes just have three, including EPSG3395, EPSG3857 and EPSG4087. I need use more. so I add Register function, the source code like :

func Register(dest EPSGCode, projString string) {
cacheLock.Lock()
projStrings[dest] = projString
cacheLock.Unlock()
}

.defs files

We don't support the "defs" files, e.g. /usr/local/share/proj_def.dat.

Cmd returns +Inf

Thank you for this great project!

I'm trying to use the command line to replicate the results from:
https://epsg.io/transform#s_srs=32617&t_srs=4326&x=632519.9000000&y=4834621.3000000

But nothing seems to work:

(base) ➜  proj git:(master) ✗ go run proj.go +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs

79.38 43.65
+Inf +Inf

unexpected newline
exit status 1
(base) ➜  proj git:(master) ✗ go run proj.go +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs

43.65 79.38
+Inf +Inf

unexpected newline
exit status 1
(base) ➜  proj git:(master) ✗ go run proj.go +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs -inverse

79.38 43.65
+Inf +Inf

unexpected newline
exit status 1
(base) ➜  proj git:(master) ✗ go run proj.go +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs -inverse

43.65 79.38
+Inf +Inf

unexpected newline
exit status 1
(base) ➜  proj git:(master) ✗ go run proj.go +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs -inverse

-79.38 43.65
+Inf +Inf
^Csignal: interrupt
(base) ➜  proj git:(master) ✗ go run proj.go +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs

-79.38 43.65
+Inf +Inf

unexpected newline
exit status 1
(base) ➜  proj git:(master) ✗ go run proj.go +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs

43.65 -79.38
+Inf -Inf

unexpected newline
exit status 1
(base) ➜  proj git:(master) ✗ go run proj.go +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs -inverse

43.65 -79.38
+Inf -Inf

unexpected newline
exit status 1
(base) ➜  proj git:(master) ✗ go run proj.go +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs -inverse

632519.9 4834621.3
lat or lon limit exceeded
exit status 1
(base) ➜  proj git:(master) ✗ go run proj.go +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs

632519.9 4834621.3
lat or lon limit exceeded
exit status 1

Removing white spaces in ProjStr code

I've come up with an alternative to this TODO:

// TODO: this is a bad hack

It uses the regexp package and the new collapse function looks like this:

func collapse(s string) string {
        re_leadclose_whtsp := regexp.MustCompile(`^[\s\p{Zs}]+|[\s\p{Zs}]+$`)
    	re_inside_whtsp := regexp.MustCompile(`[\s\p{Zs}]{2,}`)
	re_equal_whtsp := regexp.MustCompile(`\s?[=]\s?`)
    	s = re_leadclose_whtsp.ReplaceAllString(s, "")
    	s = re_inside_whtsp.ReplaceAllString(s, " ")
	s = re_equal_whtsp.ReplaceAllString(s, "=")

        return s
}

I can submit a PR if you think it solves the problem.

Documentation needed

  • Update README
    • porting principles
    • sketch of basic operation, major classes
    • work to be done next
  • Function-level comments

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.