cb-ffi-proj4 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/ffi-proj4.rb ADDED
@@ -0,0 +1,152 @@
1
+
2
+ require 'rubygems'
3
+ require 'ffi'
4
+ require 'rbconfig'
5
+
6
+ module Proj4
7
+ PROJ4_BASE = File.join(File.dirname(__FILE__), 'ffi-proj4')
8
+
9
+ autoload :Projection,
10
+ File.join(PROJ4_BASE, 'projection')
11
+ autoload :ProjXY,
12
+ File.join(PROJ4_BASE, 'projxy')
13
+ autoload :Tools,
14
+ File.join(PROJ4_BASE, 'tools')
15
+ autoload :Point,
16
+ File.join(PROJ4_BASE, 'point')
17
+
18
+ module FFIProj4
19
+ def self.proj4_library_path
20
+ return @proj4_library_paths if @proj4_library_paths
21
+
22
+ paths = if ENV['PROJ4_LIBRARY_PATH']
23
+ [ ENV['PROJ4_LIBRARY_PATH'] ]
24
+ else
25
+ [ '/usr/local/{lib64,lib}', '/opt/local/{lib64,lib}', '/usr/{lib64,lib}' ]
26
+ end
27
+
28
+ lib = if [
29
+ Config::CONFIG['arch'],
30
+ Config::CONFIG['host_os']
31
+ ].detect { |c| c =~ /darwin/ }
32
+ 'libproj.dylib'
33
+ else
34
+ 'libproj.so'
35
+ end
36
+
37
+ @proj4_library_path = Dir.glob(paths.collect { |path|
38
+ "#{path}/#{lib}"
39
+ }).first
40
+
41
+ if Config::CONFIG['host_os'] =~ /win32/
42
+ @proj4_library_path = "#{ENV['PROJ4_LIBRARY_PATH'] + '\\' if ENV['PROJ4_LIBRARY_PATH']}proj.dll"
43
+ end
44
+ @proj4_library_path
45
+ end
46
+
47
+ extend ::FFI::Library
48
+
49
+ ffi_lib(*proj4_library_path)
50
+
51
+ FFI_LAYOUT = {
52
+ :pj_get_release => [
53
+ :string
54
+ ],
55
+
56
+ :pj_transform => [
57
+ :int, :pointer, :pointer, :long, :int, :pointer, :pointer, :pointer
58
+ ],
59
+
60
+ :pj_init_plus => [
61
+ :pointer, :string
62
+ ],
63
+
64
+ :pj_free => [
65
+ :void, :pointer
66
+ ],
67
+
68
+ :pj_is_latlong => [
69
+ :int, :pointer
70
+ ],
71
+
72
+ :pj_is_geocent => [
73
+ :int, :pointer
74
+ ],
75
+
76
+ :pj_get_def => [
77
+ :string, :pointer, :int
78
+ ],
79
+
80
+ :pj_latlong_from_proj => [
81
+ :pointer, :pointer
82
+ ],
83
+
84
+ :pj_set_finder => [
85
+ :void, callback([ :string ], :string)
86
+ ],
87
+
88
+ :pj_set_searchpath => [
89
+ :void, :int, :pointer
90
+ ],
91
+
92
+ :pj_deallocate_grids => [
93
+ :void
94
+ ],
95
+
96
+ :pj_strerrno => [
97
+ :string, :int
98
+ ],
99
+
100
+ :pj_get_errno_ref => [
101
+ :pointer
102
+ ],
103
+
104
+ :pj_fwd => [
105
+ Proj4::ProjXY.by_value, Proj4::ProjXY.by_value, :pointer
106
+ ],
107
+
108
+ :pj_inv => [
109
+ Proj4::ProjXY.by_value, Proj4::ProjXY.by_value, :pointer
110
+ ],
111
+
112
+ :pj_transform => [
113
+ :int, :pointer, :pointer, :long, :int, :pointer, :pointer, :pointer
114
+ ],
115
+
116
+ :pj_datum_transform => [
117
+ :int, :pointer, :pointer, :long, :int, :pointer, :pointer, :pointer
118
+ ]
119
+ }
120
+
121
+ FFI_LAYOUT.each do |fun, ary|
122
+ ret = ary.shift
123
+ begin
124
+ self.class_eval do
125
+ attach_function(fun, ary, ret)
126
+ end
127
+ rescue FFI::NotFoundError
128
+ # that's okay
129
+ end
130
+ end
131
+ end
132
+
133
+ class << self
134
+ def version
135
+ FFIProj4.pj_get_release
136
+ end
137
+ end
138
+
139
+ module Constants
140
+ VERSION = File.read(File.join(PROJ4_BASE, %w{ .. .. VERSION })).strip
141
+ PROJ4_VERSION = if Proj4.version =~ /Rel\. (\d+)\.(\d+)\.(\d+)/
142
+ "#{$1}#{$2}#{$3}".to_f
143
+ end
144
+
145
+ RAD_TO_DEG = 57.29577951308232
146
+ DEG_TO_RAD = 0.0174532925199432958
147
+ end
148
+
149
+ ENV['PROJ_LIB'] = File.join(File.dirname(PROJ4_BASE), %w{ data }) unless ENV['PROJ_LIB']
150
+
151
+ include Constants
152
+ end
@@ -0,0 +1,119 @@
1
+
2
+ $: << File.dirname(__FILE__)
3
+ require 'test_helper'
4
+
5
+ class ProjectionTests < Test::Unit::TestCase
6
+ include TestHelper
7
+
8
+ def definition_sorter(definition)
9
+ definition.split(/\s+/).sort.join(' ')
10
+ end
11
+
12
+ def test_read_strings
13
+ tester = lambda { |expected, proj|
14
+ assert_equal(
15
+ definition_sorter(expected),
16
+ definition_sorter(Proj4::Projection.new(proj).definition)
17
+ )
18
+ }
19
+
20
+ tester[
21
+ '+init=epsg:4326 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0',
22
+ 'init=epsg:4326'
23
+ ]
24
+
25
+ tester[
26
+ '+init=epsg:31467 +proj=tmerc +lat_0=0 +lon_0=9 +k=1.000000 +x_0=3500000 +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs +towgs84=606.0,23.0,413.0',
27
+ 'init=epsg:31467'
28
+ ]
29
+
30
+ tester[
31
+ '+init=epsg:31528 +proj=utm +zone=28 +a=6378249.2 +b=6356515 +towgs84=-23,259,-9,0,0,0,0 +units=m +no_defs',
32
+ 'init=epsg:31528'
33
+ ]
34
+
35
+ tester[
36
+ '+proj=ortel +lon_0=90w +ellps=WGS84',
37
+ 'proj=ortel lon_0=90w'
38
+ ]
39
+
40
+ assert_raise(Proj4::ProjectionParseError) do
41
+ tester[
42
+ '',
43
+ 'gibberish'
44
+ ]
45
+ end
46
+ end
47
+
48
+ def test_read_arrays
49
+ tester = lambda { |expected, proj|
50
+ assert_equal(
51
+ definition_sorter(expected),
52
+ definition_sorter(Proj4::Projection.new(proj).definition)
53
+ )
54
+ }
55
+
56
+ tester[
57
+ '+init=epsg:4326 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0',
58
+ [ 'init=epsg:4326' ]
59
+ ]
60
+
61
+ tester[
62
+ '+init=epsg:31467 +proj=tmerc +lat_0=0 +lon_0=9 +k=1.000000 +x_0=3500000 +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs +towgs84=606.0,23.0,413.0',
63
+ [ 'init=epsg:31467' ]
64
+ ]
65
+
66
+ tester[
67
+ '+init=epsg:31528 +proj=utm +zone=28 +a=6378249.2 +b=6356515 +towgs84=-23,259,-9,0,0,0,0 +units=m +no_defs',
68
+ [ 'init=epsg:31528' ]
69
+ ]
70
+
71
+ tester[
72
+ '+proj=ortel +lon_0=90w +ellps=WGS84',
73
+ [ 'proj=ortel', 'lon_0=90w' ]
74
+ ]
75
+
76
+ assert_raise(Proj4::ProjectionParseError) do
77
+ tester[
78
+ '',
79
+ [ 'gibberish' ]
80
+ ]
81
+ end
82
+ end
83
+
84
+ def test_read_hashes
85
+ tester = lambda { |expected, proj|
86
+ assert_equal(
87
+ definition_sorter(expected),
88
+ definition_sorter(Proj4::Projection.new(proj).definition)
89
+ )
90
+ }
91
+
92
+ tester[
93
+ '+init=epsg:4326 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0',
94
+ { :init => 'epsg:4326' }
95
+ ]
96
+
97
+ tester[
98
+ '+init=epsg:31467 +proj=tmerc +lat_0=0 +lon_0=9 +k=1.000000 +x_0=3500000 +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs +towgs84=606.0,23.0,413.0',
99
+ { :init => 'epsg:31467' }
100
+ ]
101
+
102
+ tester[
103
+ '+init=epsg:31528 +proj=utm +zone=28 +a=6378249.2 +b=6356515 +towgs84=-23,259,-9,0,0,0,0 +units=m +no_defs',
104
+ { :init => 'epsg:31528' }
105
+ ]
106
+
107
+ tester[
108
+ '+lon_0=90w +proj=ortel +ellps=WGS84',
109
+ { :proj => 'ortel', :lon_0 => '90w' }
110
+ ]
111
+
112
+ assert_raise(Proj4::ProjectionParseError) do
113
+ tester[
114
+ '',
115
+ { :proj => 'gibberish' }
116
+ ]
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,29 @@
1
+
2
+ require 'rubygems'
3
+ require 'test/unit'
4
+
5
+ if ENV['USE_BINARY_PROJ4']
6
+ require 'proj4_ruby'
7
+ else
8
+ require File.join(File.dirname(__FILE__), %w{ .. lib ffi-proj4 })
9
+ end
10
+
11
+ puts "Ruby version #{RUBY_VERSION} - #{RbConfig::CONFIG['RUBY_INSTALL_NAME']}"
12
+ puts "ffi-proj4 version #{Proj4::VERSION}"
13
+ puts "PROJ version #{Proj4.version}"
14
+ if defined?(Proj4::FFIProj4)
15
+ puts "Using #{Array(Proj4::FFIProj4.proj4_library_path).join(', ')}"
16
+ end
17
+ puts "Using PROJ_LIB #{ENV['PROJ_LIB']}"
18
+
19
+ module TestHelper
20
+ TOLERANCE = 0.00000001
21
+
22
+ def self.included(base)
23
+ base.class_eval do
24
+ end
25
+ end
26
+
27
+ def setup
28
+ end
29
+ end
@@ -0,0 +1,90 @@
1
+
2
+ $: << File.dirname(__FILE__)
3
+ require 'test_helper'
4
+
5
+ class TransformationTests < Test::Unit::TestCase
6
+ include TestHelper
7
+
8
+ def setup
9
+ @proj_wgs84 = Proj4::Projection.new(["init=epsg:4326"])
10
+ @proj_gk = Proj4::Projection.new(["init=epsg:31467"])
11
+ @proj_merc = Proj4::Projection.new(["proj=merc"])
12
+ @lon = 8.4293092923
13
+ @lat = 48.9896114523
14
+ @rw = 3458305
15
+ @hw = 5428192
16
+ @zw = -5.1790915237
17
+ end
18
+
19
+ def test_gk_to_wgs84
20
+ to = @proj_gk.transform(@proj_wgs84, @rw, @hw, @zw)
21
+
22
+ assert_in_delta @lon, to.x * Proj4::RAD_TO_DEG, TOLERANCE
23
+ assert_in_delta @lat, to.y * Proj4::RAD_TO_DEG, TOLERANCE
24
+ assert_in_delta 0, to.z, TOLERANCE
25
+ end
26
+
27
+ def test_wgs84_to_gk
28
+ point = @proj_wgs84.transform(
29
+ @proj_gk,
30
+ @lon * Proj4::DEG_TO_RAD,
31
+ @lat * Proj4::DEG_TO_RAD,
32
+ 0
33
+ )
34
+ assert_equal @rw, point.x.round
35
+ assert_equal @hw, point.y.round
36
+ assert_in_delta @zw, point.z, TOLERANCE
37
+ end
38
+
39
+ def test_no_dst_proj
40
+ assert_raise ArgumentError do
41
+ @proj_wgs84.transform(
42
+ nil,
43
+ @lon * Proj4::DEG_TO_RAD,
44
+ @lat * Proj4::DEG_TO_RAD,
45
+ 0
46
+ )
47
+ end
48
+ end
49
+
50
+ def test_mercator_at_pole_raise
51
+ assert_raise Proj4::TransformError do
52
+ @proj_wgs84.transform(
53
+ @proj_merc,
54
+ 0,
55
+ 90 * Proj4::DEG_TO_RAD,
56
+ 0
57
+ )
58
+ end
59
+ end
60
+ end
61
+
62
+ class SimpleTransformationTests < Test::Unit::TestCase
63
+ include TestHelper
64
+
65
+ def setup
66
+ @proj_gk = Proj4::Projection.new(["init=epsg:31467"])
67
+ @lon = 8.4302123334
68
+ @lat = 48.9906726079
69
+ @rw = 3458305
70
+ @hw = 5428192
71
+ end
72
+
73
+ def test_forward_gk
74
+ result = @proj_gk.forward_rad(@lon, @lat)
75
+ assert_in_delta @rw, result.x, 0.1
76
+ assert_in_delta @hw, result.y, 0.1
77
+ end
78
+
79
+ def test_inverse_gk
80
+ result = @proj_gk.inverse(@rw, @hw)
81
+ assert_in_delta @lon, Proj4::Tools.rad_to_deg(result.x), TOLERANCE
82
+ assert_in_delta @lat, Proj4::Tools.rad_to_deg(result.y), TOLERANCE
83
+ end
84
+
85
+ def test_out_of_bounds
86
+ assert_raise Proj4::TransformError do
87
+ @proj_gk.forward_deg(190, 92)
88
+ end
89
+ end
90
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cb-ffi-proj4
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 3
10
+ version: 0.0.3
11
+ platform: ruby
12
+ authors:
13
+ - J Smith
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-06-27 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: An ffi wrapper for the PROJ.4 Cartographic Projections library.
23
+ email: dark.panda@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - MIT-LICENSE
32
+ - Rakefile
33
+ - VERSION
34
+ - data/GL27
35
+ - data/MD
36
+ - data/TN
37
+ - data/WI
38
+ - data/WO
39
+ - data/conus
40
+ - data/epsg
41
+ - data/epsg-deprecated
42
+ - data/esri
43
+ - data/esri.extra
44
+ - data/hawaii
45
+ - data/nad.lst
46
+ - data/nad27
47
+ - data/nad83
48
+ - data/ntv1_can.dat
49
+ - data/null
50
+ - data/other.extra
51
+ - data/proj_def.dat
52
+ - data/prvi
53
+ - data/stgeorge
54
+ - data/stlrnc
55
+ - data/stpaul
56
+ - data/world
57
+ - lib/ffi-proj4.rb
58
+ - lib/ffi-proj4/point.rb
59
+ - lib/ffi-proj4/projection.rb
60
+ - lib/ffi-proj4/projxy.rb
61
+ - lib/ffi-proj4/tools.rb
62
+ - test/projection_tests.rb
63
+ - test/test_helper.rb
64
+ - test/transformation_tests.rb
65
+ has_rdoc: true
66
+ homepage: http://github.com/dark-panda/ffi-proj4
67
+ licenses: []
68
+
69
+ post_install_message:
70
+ rdoc_options: []
71
+
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ hash: 3
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ requirements: []
93
+
94
+ rubyforge_project:
95
+ rubygems_version: 1.6.2
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: An ffi wrapper for the PROJ.4 Cartographic Projections library.
99
+ test_files: []
100
+