Skip to content

Commit

Permalink
Merge pull request #10 from rgeo/proj-version-upgrade
Browse files Browse the repository at this point in the history
Upgrade PROJ API to 6.2+
  • Loading branch information
keithdoggett authored Apr 28, 2021
2 parents 24b1cdf + dcdb005 commit 4cc50ce
Show file tree
Hide file tree
Showing 23 changed files with 499 additions and 225 deletions.
54 changes: 54 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: CI

on:
push:
branches:
- master
pull_request:

jobs:
Build:
strategy:
fail-fast: false
matrix:
ruby:
- head
- "3.0"
- "2.7"
- "2.6"
- "2.5"
os:
- ubuntu
- macos
runs-on: ${{ matrix.os }}-latest
continue-on-error: ${{ matrix.ruby == 'head' || matrix.os == 'macos' }}
name: Ruby ${{ matrix.ruby }} (${{ matrix.os }})
steps:
- uses: actions/checkout@v2
- name: Install Packages (Linux)
if: matrix.os == 'ubuntu'
run: |
sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable
sudo apt-get install libgeos-dev libproj-dev proj-bin -y
- name: Install Packages (Mac)
if: matrix.os == 'macos'
run: brew install geos proj
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: false
- name: Bundle Install
run: |
bundle install
- name: Test
run: bundle exec rake
RuboCop:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
- run: |
bundle exec rubocop --color --parallel
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
inherit_from: .rubocop_todo.yml

AllCops:
TargetRubyVersion: 2.4
TargetRubyVersion: 2.5

Layout/ParameterAlignment:
Enabled: false
Expand Down
28 changes: 0 additions & 28 deletions .travis.yml

This file was deleted.

2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ source "https://rubygems.org"

gemspec

gem "pry-byebug" unless ENV["TRAVIS"]
gem "pry-byebug" unless ENV["CI"]
4 changes: 4 additions & 0 deletions Hisory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### 3.0.0 / 2021-04-28

* Support Proj 6.2+ #10
* Add support for various projection representations #10
135 changes: 118 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,26 @@ Documentation about `proj.4` is available at [http://proj4.org/](http://proj4.or

## Installation

### Install PROJ

Install `proj` using your package manager:

#### Homebrew

```sh
brew install proj
```

#### Ubuntu/Debian

```sh
apt-get install libproj-dev proj-bin
```

Or download binaries at https://proj.org/

Note that version 3.x requires PROJ 6.2+. This should be the default on most systems, but in some cases, specific repositories will need to be added to the package manager.

Add this line to your Gemfile:

```ruby
Expand All @@ -23,23 +43,6 @@ Or install it yourself as:

$ gem install rgeo-proj4

## Usage

Install `proj.4` using your package manager:

### Homebrew
```sh
brew install proj
```

### Apt

```sh
apt-get install libproj-dev
```

Or download binaries at https://proj.org/

By default, the gem looks for the Proj4 library in the following paths:

```
Expand All @@ -57,6 +60,104 @@ By default, the gem looks for the Proj4 library in the following paths:
If Proj4 is installed in a different location, you must provide its
installation prefix directory using the `--with-proj-dir` option.

## Usage

The `rgeo-proj4` gem can be used by defining `CoordSys::Proj4` objects, as a part of an `RGeo::Geographic.projected_factory`, or as an attribute of other factories.

### RGeo::CoordSys::Proj4

This is the lowest level module to transform between coordinate systems and all of the other methods ultimately rely on this object. The object is created with a [valid PROJ definition](https://proj.org/development/reference/functions.html#c.proj_create) which is used to define a coordinate reference system (CRS). Note that 2 `Proj4` objects need to be defined to transform between CRS's.

In addition to allowing transformations, this object can return information about the CRS.

```ruby
require 'rgeo'
require 'rgeo/proj4'

# define CRS's
geography = RGeo::CoordSys::Proj4.create("EPSG:4326")
projection = RGeo::CoordSys::Proj4.create("EPSG:3857")

x,y = RGeo::CoordSys::Proj4.transform_coords(projection, geography, -8367354.015764384, 4859054.160863457, nil)

p x
# => -75.16522
p y
# => 39.95258299
```

Other information can be shown from the `Proj4` object:

```ruby
require 'rgeo'
require 'rgeo/proj4'

projection = RGeo::CoordSys::Proj4.create("EPSG:3857")
p projection.canconical_str
# => "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs"

p projection.auth_name
# => "EPSG:3857"

p projection.as_text
# => PROJCRS[\"WGS 84 / Pseudo-Mercator\",BASEGEOGCRS[\"WGS 84\",DATUM[\"World Geodetic System 1984\",ELLIPSOID[\"WGS 84\",6378137,298.257223563,LENGTHUNIT[\"metre\",1]]],PRIMEM[\"Greenwich\",0,ANGLEUNIT[\"degree\",0.0174532925199433]],ID[\"EPSG\",4326]],CONVERSION[\"Popular Visualisation Pseudo-Mercator\",METHOD[\"Popular Visualisation Pseudo Mercator\",ID[\"EPSG\",1024]],PARAMETER[\"Latitude of natural origin\",0,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8801]],PARAMETER[\"Longitude of natural origin\",0,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8802]],PARAMETER[\"False easting\",0,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8806]],PARAMETER[\"False northing\",0,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8807]]],CS[Cartesian,2],AXIS[\"easting (X)\",east,ORDER[1],LENGTHUNIT[\"metre\",1]],AXIS[\"northing (Y)\",north,ORDER[2],LENGTHUNIT[\"metre\",1]],USAGE[SCOPE[\"unknown\"],AREA[\"World - 85\xC2\xB0S to 85\xC2\xB0N\"],BBOX[-85.06,-180,85.06,180]],ID[\"EPSG\",3857]]
```

### Projected Factory

The projected factory is a compound geographic factory that is useful for converting from lon/lat to the specified CRS.

```ruby
require 'rgeo'
require 'rgeo/proj4'

factory = RGeo::Geographic.projected_factory(projection_proj4: "EPSG:3857", projection_srid: 3857)

p factory.projection_factory
# => #<RGeo::Geos::CAPIFactory srid=3857 bufres=1 flags=8>

p factory.projection_factory.proj4
# => #<RGeo::CoordSys::Proj4 "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs">

p factory.projection_factory.proj4.auth_name
# => "EPSG:3857"

pt = factory.point(-75.16522, 39.95258299)
p pt.projection
# => #<RGeo::Geos::CAPIPointImpl "POINT (-8367354.015764384 4859054.159411294)">

p factory.unproject(pt.projection)
# => #<RGeo::Geographic::ProjectedPointImpl "POINT (-75.16522 39.952582989999996)">
```

### Feature::Cast

This method allows you to perform projections between more than just a lon/lat system. As long as 2 factories with valid Proj4 CRS's are defined, it can project between the CRS's.

```ruby
require 'rgeo'
require 'rgeo/proj4'

geography = RGeo::Geos.factory(proj4: "EPSG:4326", srid: 4326)
projection = RGeo::Geos.factory(proj4: "EPSG:3857", srid: 3857)

p geography.proj4.auth_name
# => "EPSG:4326"
p projection.proj4.auth_name
# => "EPSG:3857"

proj_point = projection.parse_wkt("POINT (-8367354.015764384 4859054.159411294)")

geo_point = RGeo::Feature.cast(proj_point, project: true, factory: geography)
p geo_point
# => #<RGeo::Geos::CAPIPointImpl "POINT (-75.16522 39.952582989999996)">

proj_point2 = RGeo::Feature.cast(geo_point, project: true, factory: projection)

p proj_point == proj_point2
# => true
```

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run
Expand Down
10 changes: 7 additions & 3 deletions ext/proj4_c_impl/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,19 @@

found_proj_ = false
header_dirs_, lib_dirs_ = dir_config("proj", header_dirs_, lib_dirs_)
dflag = "-DACCEPT_USE_OF_DEPRECATED_PROJ_API_H"
if have_header("proj_api.h", nil, dflag)
if have_header("proj.h")
$libs << " -lproj"
if have_func("pj_init_plus", "proj_api.h", dflag)

if have_func("proj_create", "proj.h")
found_proj_ = true
have_func("proj_create_crs_to_crs_from_pj", "proj.h")
have_func("proj_normalize_for_visualization", "proj.h")
else
$libs.gsub!(" -lproj", "")
end
end
have_func("rb_gc_mark_movable")

unless found_proj_
puts "**** WARNING: Unable to find Proj headers or Proj version is too old."
puts "**** Compiling without Proj support."
Expand Down
Loading

0 comments on commit 4cc50ce

Please sign in to comment.