proj4rb 1.0.0 → 2.0.0
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.
- checksums.yaml +5 -5
 - data/ChangeLog +46 -0
 - data/Gemfile +4 -0
 - data/README.rdoc +158 -148
 - data/Rakefile +26 -41
 - data/lib/area.rb +32 -0
 - data/lib/config.rb +70 -0
 - data/lib/context.rb +103 -0
 - data/lib/coordinate.rb +197 -0
 - data/lib/crs.rb +206 -0
 - data/lib/ellipsoid.rb +42 -0
 - data/lib/error.rb +18 -0
 - data/lib/operation.rb +43 -0
 - data/lib/pj_object.rb +82 -0
 - data/lib/point.rb +72 -0
 - data/lib/prime_meridian.rb +40 -0
 - data/lib/proj.rb +31 -0
 - data/lib/proj4.rb +3 -469
 - data/lib/projection.rb +207 -0
 - data/lib/transformation.rb +61 -0
 - data/lib/unit.rb +54 -0
 - data/proj4rb.gemspec +31 -0
 - data/test/abstract_test.rb +7 -0
 - data/test/context_test.rb +82 -0
 - data/test/coordinate_test.rb +35 -0
 - data/test/crs_test.rb +373 -0
 - data/test/ellipsoid_test.rb +34 -0
 - data/test/operation_test.rb +29 -0
 - data/test/prime_meridians_test.rb +33 -0
 - data/test/proj_test.rb +17 -0
 - data/test/projection_test.rb +224 -0
 - data/test/transformation_test.rb +68 -0
 - data/test/unit_test.rb +47 -0
 - metadata +82 -77
 - data/data/GL27 +0 -22
 - data/data/MD +0 -0
 - data/data/TN +0 -0
 - data/data/WI +0 -0
 - data/data/WO +0 -0
 - data/data/conus +0 -0
 - data/data/epsg +0 -5443
 - data/data/epsg-deprecated +0 -2
 - data/data/esri +0 -5937
 - data/data/esri.extra +0 -948
 - data/data/hawaii +0 -0
 - data/data/nad.lst +0 -142
 - data/data/nad27 +0 -809
 - data/data/nad83 +0 -744
 - data/data/ntv1_can.dat +0 -0
 - data/data/null +0 -0
 - data/data/other.extra +0 -49
 - data/data/proj_def.dat +0 -17
 - data/data/prvi +0 -0
 - data/data/stgeorge +0 -0
 - data/data/stlrnc +0 -0
 - data/data/stpaul +0 -0
 - data/data/world +0 -212
 - data/example/basic.rb +0 -18
 - data/example/list-datums.rb +0 -17
 - data/example/list-ellipsoids.rb +0 -17
 - data/example/list-errors.rb +0 -11
 - data/example/list-prime-meridians.rb +0 -17
 - data/example/list-projection-types.rb +0 -17
 - data/example/list-units.rb +0 -17
 - data/example/version.rb +0 -8
 - data/ext/Makefile +0 -238
 - data/ext/extconf.rb +0 -16
 - data/ext/mkmf.log +0 -103
 - data/ext/out.log +0 -0
 - data/ext/proj4_ruby-x64-mingw32.def +0 -2
 - data/ext/proj4_ruby.so +0 -0
 - data/ext/projrb.c +0 -566
 - data/ext/projrb.o +0 -0
 - data/ext/vc/proj4_ruby.sln +0 -19
 - data/ext/vc/proj4_ruby.vcproj +0 -208
 - data/test/test_constants.rb +0 -18
 - data/test/test_create_projection.rb +0 -63
 - data/test/test_datums.rb +0 -45
 - data/test/test_ellipsoids.rb +0 -46
 - data/test/test_errors.rb +0 -66
 - data/test/test_init_projection.rb +0 -109
 - data/test/test_prime_meridians.rb +0 -45
 - data/test/test_projection_type.rb +0 -44
 - data/test/test_simple_projection.rb +0 -58
 - data/test/test_suite.rb +0 -14
 - data/test/test_transform.rb +0 -115
 - data/test/test_units.rb +0 -46
 
    
        data/lib/projection.rb
    ADDED
    
    | 
         @@ -0,0 +1,207 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Proj
         
     | 
| 
      
 4 
     | 
    
         
            +
              # @deprecated This class is *DEPRECATED.* It will be removed when Proj 7 is released and removes the
         
     | 
| 
      
 5 
     | 
    
         
            +
              #   underlying API's this class uses. Code should be ported to use Crs and Transformation objects.
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Projection
         
     | 
| 
      
 7 
     | 
    
         
            +
                def self.parse(value)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  values = case value
         
     | 
| 
      
 9 
     | 
    
         
            +
                             when Array
         
     | 
| 
      
 10 
     | 
    
         
            +
                               value
         
     | 
| 
      
 11 
     | 
    
         
            +
                             when String
         
     | 
| 
      
 12 
     | 
    
         
            +
                               value.strip.split(' ')
         
     | 
| 
      
 13 
     | 
    
         
            +
                             when Hash
         
     | 
| 
      
 14 
     | 
    
         
            +
                               array = []
         
     | 
| 
      
 15 
     | 
    
         
            +
                               value.each_pair do |key, value|
         
     | 
| 
      
 16 
     | 
    
         
            +
                                 key = "+#{key}"
         
     | 
| 
      
 17 
     | 
    
         
            +
                                 array << (value.nil? ? key : "#{key}=#{value}")
         
     | 
| 
      
 18 
     | 
    
         
            +
                               end
         
     | 
| 
      
 19 
     | 
    
         
            +
                               array
         
     | 
| 
      
 20 
     | 
    
         
            +
                             when Projection
         
     | 
| 
      
 21 
     | 
    
         
            +
                               value.getDef.split(' ')
         
     | 
| 
      
 22 
     | 
    
         
            +
                             else
         
     | 
| 
      
 23 
     | 
    
         
            +
                               raise ArgumentError, "Unknown type #{value.class} for projection definition"
         
     | 
| 
      
 24 
     | 
    
         
            +
                           end
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def self.finalize(pointer)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  proc do
         
     | 
| 
      
 29 
     | 
    
         
            +
                    Api.pj_free(pointer)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                # Projection classes are created using Proj4 strings which consist of a number of parameters.
         
     | 
| 
      
 34 
     | 
    
         
            +
                # For more information please see the +opt arguments section at https://proj.org/apps/proj.html.
         
     | 
| 
      
 35 
     | 
    
         
            +
                #
         
     | 
| 
      
 36 
     | 
    
         
            +
                # @param value [string, array, hash] Parameters can be specified as strings, arrays or hashes.
         
     | 
| 
      
 37 
     | 
    
         
            +
                #
         
     | 
| 
      
 38 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 39 
     | 
    
         
            +
                #   proj = Projection.new("+proj=utm +zone=21 +units=m")
         
     | 
| 
      
 40 
     | 
    
         
            +
                #   proj = Projection.new ["+proj=utm", "+zone=21", "+units=m"]
         
     | 
| 
      
 41 
     | 
    
         
            +
                #   proj = Projection.new("proj" => "utm", "zone" => "21", "units" => "m")
         
     | 
| 
      
 42 
     | 
    
         
            +
                #
         
     | 
| 
      
 43 
     | 
    
         
            +
                # With all variants the plus sign in front of the keys is optional.
         
     | 
| 
      
 44 
     | 
    
         
            +
                def initialize(value)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  params = self.class.parse(value)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  p_params = FFI::MemoryPointer.new(:pointer, params.length)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  params.each_with_index do |param, i|
         
     | 
| 
      
 48 
     | 
    
         
            +
                    p_param = FFI::MemoryPointer.from_string(param)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    p_params[i].write_pointer(p_param)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  @pointer = Api.pj_init(params.count, p_params)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  self.check_error
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  ObjectSpace.define_finalizer(self, self.class.finalize(@pointer))
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                def check_error
         
     | 
| 
      
 59 
     | 
    
         
            +
                  ptr = Api.pj_get_errno_ref
         
     | 
| 
      
 60 
     | 
    
         
            +
                  errno = ptr.read_int
         
     | 
| 
      
 61 
     | 
    
         
            +
                  if errno != 0
         
     | 
| 
      
 62 
     | 
    
         
            +
                    # If we don't reset the error code it hangs around. This doesn't seem documented anyplace?
         
     | 
| 
      
 63 
     | 
    
         
            +
                    ptr.write_int(0)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    Error.check(errno)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                def to_ptr
         
     | 
| 
      
 70 
     | 
    
         
            +
                  @pointer
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                # Returns projection definitions
         
     | 
| 
      
 74 
     | 
    
         
            +
                #
         
     | 
| 
      
 75 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 76 
     | 
    
         
            +
                def getDef
         
     | 
| 
      
 77 
     | 
    
         
            +
                  Api.pj_get_def(self, 0)
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                # Returns if this is a geocentric projection
         
     | 
| 
      
 81 
     | 
    
         
            +
                #
         
     | 
| 
      
 82 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 83 
     | 
    
         
            +
                def isGeocent?
         
     | 
| 
      
 84 
     | 
    
         
            +
                  Api::pj_is_geocent(self)
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
                alias :isGeocentric? :isGeocent?
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                # Returns if this is a lat/long projection
         
     | 
| 
      
 89 
     | 
    
         
            +
                #
         
     | 
| 
      
 90 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 91 
     | 
    
         
            +
                def isLatLong?
         
     | 
| 
      
 92 
     | 
    
         
            +
                  Api::pj_is_latlong(self)
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                # Get the ID of this projection.
         
     | 
| 
      
 96 
     | 
    
         
            +
                #
         
     | 
| 
      
 97 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 98 
     | 
    
         
            +
                def projection
         
     | 
| 
      
 99 
     | 
    
         
            +
                  getDef =~ /\+proj=(.+?) / ?  $1 : nil
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                # Get the ID of the datum used in this projection.
         
     | 
| 
      
 103 
     | 
    
         
            +
                #
         
     | 
| 
      
 104 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 105 
     | 
    
         
            +
                def datum
         
     | 
| 
      
 106 
     | 
    
         
            +
                  getDef =~ /\+datum=(.+?) / ? $1 : nil
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                # Get definition of projection in typical inspect format (#<Proj::Projection +init=... +proj=... ...>).
         
     | 
| 
      
 110 
     | 
    
         
            +
                #
         
     | 
| 
      
 111 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 112 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 113 
     | 
    
         
            +
                  "#<#{self.class.name}#{getDef}>"
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                # Forward projection of a point. Returns a copy of the point object with coordinates projected.
         
     | 
| 
      
 117 
     | 
    
         
            +
                #
         
     | 
| 
      
 118 
     | 
    
         
            +
                # @param point [Point] in radians
         
     | 
| 
      
 119 
     | 
    
         
            +
                # @return [Point] in cartesian coordinates
         
     | 
| 
      
 120 
     | 
    
         
            +
                def forward(point)
         
     | 
| 
      
 121 
     | 
    
         
            +
                  struct = Api.pj_fwd(point, self)
         
     | 
| 
      
 122 
     | 
    
         
            +
                  self.check_error
         
     | 
| 
      
 123 
     | 
    
         
            +
                  Point.from_pointer(struct)
         
     | 
| 
      
 124 
     | 
    
         
            +
                end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                # Convenience function for calculating a forward projection with degrees instead of radians.
         
     | 
| 
      
 127 
     | 
    
         
            +
                #
         
     | 
| 
      
 128 
     | 
    
         
            +
                # @param point [Point] in degrees
         
     | 
| 
      
 129 
     | 
    
         
            +
                # @return [Point] in cartesian coordinates
         
     | 
| 
      
 130 
     | 
    
         
            +
                def forwardDeg(point)
         
     | 
| 
      
 131 
     | 
    
         
            +
                  forward(point.to_radians)
         
     | 
| 
      
 132 
     | 
    
         
            +
                end
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                # Projects all points in a collection.
         
     | 
| 
      
 135 
     | 
    
         
            +
                #
         
     | 
| 
      
 136 
     | 
    
         
            +
                # @param collection [Enumerable<Point>] Points specified in radians
         
     | 
| 
      
 137 
     | 
    
         
            +
                # @return [Enumerable<Point>] Points specified in cartesian coordinates
         
     | 
| 
      
 138 
     | 
    
         
            +
                def forward_all(collection)
         
     | 
| 
      
 139 
     | 
    
         
            +
                  collection.map do |point|
         
     | 
| 
      
 140 
     | 
    
         
            +
                    forward(point)
         
     | 
| 
      
 141 
     | 
    
         
            +
                  end
         
     | 
| 
      
 142 
     | 
    
         
            +
                end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                # Inverse projection of a point. Returns a copy of the point object with coordinates projected.
         
     | 
| 
      
 145 
     | 
    
         
            +
                #
         
     | 
| 
      
 146 
     | 
    
         
            +
                # @param point [Point] in cartesian coordinates
         
     | 
| 
      
 147 
     | 
    
         
            +
                # @return [Point] in radians
         
     | 
| 
      
 148 
     | 
    
         
            +
                def inverse(point)
         
     | 
| 
      
 149 
     | 
    
         
            +
                  struct = Api.pj_inv(point, self)
         
     | 
| 
      
 150 
     | 
    
         
            +
                  self.check_error
         
     | 
| 
      
 151 
     | 
    
         
            +
                  Point.from_pointer(struct)
         
     | 
| 
      
 152 
     | 
    
         
            +
                end
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
                # Convenience function for calculating an inverse projection with the result in degrees instead of radians.
         
     | 
| 
      
 155 
     | 
    
         
            +
                #
         
     | 
| 
      
 156 
     | 
    
         
            +
                # @param point [Point] in cartesian coordinates
         
     | 
| 
      
 157 
     | 
    
         
            +
                # @return [Point] in degrees
         
     | 
| 
      
 158 
     | 
    
         
            +
                def inverseDeg(point)
         
     | 
| 
      
 159 
     | 
    
         
            +
                  result = inverse(point)
         
     | 
| 
      
 160 
     | 
    
         
            +
                  result.to_degrees
         
     | 
| 
      
 161 
     | 
    
         
            +
                end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                # Inverse projection of all points in a collection.
         
     | 
| 
      
 164 
     | 
    
         
            +
                #
         
     | 
| 
      
 165 
     | 
    
         
            +
                # @param collection [Enumerable<Point>] Points specified in cartesian coordinates
         
     | 
| 
      
 166 
     | 
    
         
            +
                # @return [Enumerable<Point>] Points specified in radians
         
     | 
| 
      
 167 
     | 
    
         
            +
                def inverse_all(collection)
         
     | 
| 
      
 168 
     | 
    
         
            +
                  collection.map do |point|
         
     | 
| 
      
 169 
     | 
    
         
            +
                    inverse(point)
         
     | 
| 
      
 170 
     | 
    
         
            +
                  end
         
     | 
| 
      
 171 
     | 
    
         
            +
                end
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                # Transforms a point from one projection to another.
         
     | 
| 
      
 174 
     | 
    
         
            +
                #
         
     | 
| 
      
 175 
     | 
    
         
            +
                # @param other [Projection]
         
     | 
| 
      
 176 
     | 
    
         
            +
                # @param point [Point]
         
     | 
| 
      
 177 
     | 
    
         
            +
                # @return [Point]
         
     | 
| 
      
 178 
     | 
    
         
            +
                def transform(other, point)
         
     | 
| 
      
 179 
     | 
    
         
            +
                  p_x = FFI::MemoryPointer.new(:double, 1)
         
     | 
| 
      
 180 
     | 
    
         
            +
                  p_x.write_double(point.x)
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                  p_y = FFI::MemoryPointer.new(:double, 1)
         
     | 
| 
      
 183 
     | 
    
         
            +
                  p_y.write_double(point.y)
         
     | 
| 
      
 184 
     | 
    
         
            +
             
     | 
| 
      
 185 
     | 
    
         
            +
                  p_z = FFI::MemoryPointer.new(:double, 1)
         
     | 
| 
      
 186 
     | 
    
         
            +
                  p_z.write_double(0)
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
                  a = Api.pj_transform(self, other, 1, 1, p_x, p_y, p_z)
         
     | 
| 
      
 189 
     | 
    
         
            +
                  self.check_error
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
                  Point.new(p_x.read_double, p_y.read_double)
         
     | 
| 
      
 192 
     | 
    
         
            +
                end
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                # Transforms all points in a collection from one projection to
         
     | 
| 
      
 195 
     | 
    
         
            +
                # another. The +collection+ object must implement the +each+,
         
     | 
| 
      
 196 
     | 
    
         
            +
                # +clear+, and << methods (just like an Array) for this to work.
         
     | 
| 
      
 197 
     | 
    
         
            +
                #
         
     | 
| 
      
 198 
     | 
    
         
            +
                # @param other [Projection]
         
     | 
| 
      
 199 
     | 
    
         
            +
                # @param collection [Enumerable, Point]
         
     | 
| 
      
 200 
     | 
    
         
            +
                # @return [Enumerable, Point]
         
     | 
| 
      
 201 
     | 
    
         
            +
                def transform_all(other, collection)
         
     | 
| 
      
 202 
     | 
    
         
            +
                  collection.map do |point|
         
     | 
| 
      
 203 
     | 
    
         
            +
                    transform(other, point)
         
     | 
| 
      
 204 
     | 
    
         
            +
                  end
         
     | 
| 
      
 205 
     | 
    
         
            +
                end
         
     | 
| 
      
 206 
     | 
    
         
            +
              end
         
     | 
| 
      
 207 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,61 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Proj
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Transformation objects convert {Coordinate Coordinates} from one {Crs} to another.
         
     | 
| 
      
 3 
     | 
    
         
            +
              class Transformation < PjObject
         
     | 
| 
      
 4 
     | 
    
         
            +
                # Transforms a {Coordinate} from the source {Crs} to the target {Crs}. Coordinates should be expressed in
         
     | 
| 
      
 5 
     | 
    
         
            +
                # the units and axis order of the definition of the source CRS. The returned transformed coordinate will
         
     | 
| 
      
 6 
     | 
    
         
            +
                # be in the units and axis order of the definition of the target CRS.
         
     | 
| 
      
 7 
     | 
    
         
            +
                #
         
     | 
| 
      
 8 
     | 
    
         
            +
                # For most geographic Crses, the units will be in degrees. For geographic CRS defined by the EPSG authority,
         
     | 
| 
      
 9 
     | 
    
         
            +
                # the order of coordinates is latitude first, longitude second. When using a PROJ initialization string,
         
     | 
| 
      
 10 
     | 
    
         
            +
                # on contrary, the order will be longitude first, latitude second.
         
     | 
| 
      
 11 
     | 
    
         
            +
                #
         
     | 
| 
      
 12 
     | 
    
         
            +
                # For projected CRS, the units may vary (metre, us-foot, etc..).
         
     | 
| 
      
 13 
     | 
    
         
            +
                #
         
     | 
| 
      
 14 
     | 
    
         
            +
                # For projected CRS defined by the EPSG authority, and with EAST / NORTH directions, the axis order might be
         
     | 
| 
      
 15 
     | 
    
         
            +
                # easting first, northing second, or the reverse. When using a PROJ string, the order will be
         
     | 
| 
      
 16 
     | 
    
         
            +
                # easting first, northing second, except if the +axis parameter modifies it.
         
     | 
| 
      
 17 
     | 
    
         
            +
                #
         
     | 
| 
      
 18 
     | 
    
         
            +
                # @param source [Crs | String] - The source Crs. See the Crs documentation for the string format
         
     | 
| 
      
 19 
     | 
    
         
            +
                # @param target [Crs | String] - The target Crs. See the Crs documentation for the string format
         
     | 
| 
      
 20 
     | 
    
         
            +
                # @param context [Context]
         
     | 
| 
      
 21 
     | 
    
         
            +
                def initialize(source, target, context=nil)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  pointer = if source.is_a?(Crs) && target.is_a?(Crs)
         
     | 
| 
      
 23 
     | 
    
         
            +
                              if Api.method_defined?(:proj_create_crs_to_crs_from_pj)
         
     | 
| 
      
 24 
     | 
    
         
            +
                                Api.proj_create_crs_to_crs_from_pj(self.context, source, target, nil, nil)
         
     | 
| 
      
 25 
     | 
    
         
            +
                              else
         
     | 
| 
      
 26 
     | 
    
         
            +
                                Api.proj_create_crs_to_crs(self.context, source.definition, target.definition, nil)
         
     | 
| 
      
 27 
     | 
    
         
            +
                              end
         
     | 
| 
      
 28 
     | 
    
         
            +
                            else
         
     | 
| 
      
 29 
     | 
    
         
            +
                              Api.proj_create_crs_to_crs(self.context, source, target, nil)
         
     | 
| 
      
 30 
     | 
    
         
            +
                            end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  if pointer.null?
         
     | 
| 
      
 33 
     | 
    
         
            +
                    Error.check
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  super(pointer, context)
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                # Transforms a {Coordinate} from the source {Crs} to the target {Crs}. Coordinates should be expressed in
         
     | 
| 
      
 40 
     | 
    
         
            +
                # the units and axis order of the definition of the source CRS. The returned transformed coordinate will
         
     | 
| 
      
 41 
     | 
    
         
            +
                # be in the units and axis order of the definition of the target CRS.
         
     | 
| 
      
 42 
     | 
    
         
            +
                #
         
     | 
| 
      
 43 
     | 
    
         
            +
                # @param coord [Coordinate]
         
     | 
| 
      
 44 
     | 
    
         
            +
                # @return [Coordinate]
         
     | 
| 
      
 45 
     | 
    
         
            +
                def forward(coord)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  struct = Api.proj_trans(self, :PJ_FWD, coord)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  Coordinate.from_coord(struct)
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                # Transforms a {Coordinate} from the target {Crs} to the source {Crs}. Coordinates should be expressed in
         
     | 
| 
      
 51 
     | 
    
         
            +
                # the units and axis order of the definition of the source CRS. The returned transformed coordinate will
         
     | 
| 
      
 52 
     | 
    
         
            +
                # be in the units and axis order of the definition of the target CRS.
         
     | 
| 
      
 53 
     | 
    
         
            +
                #
         
     | 
| 
      
 54 
     | 
    
         
            +
                # @param coord [Coordinate]
         
     | 
| 
      
 55 
     | 
    
         
            +
                # @return [Coordinate]
         
     | 
| 
      
 56 
     | 
    
         
            +
                def inverse(coord)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  struct = Api.proj_trans(self, :PJ_INV, coord)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  Coordinate.from_coord(struct)
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/unit.rb
    ADDED
    
    | 
         @@ -0,0 +1,54 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Proj
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Unit
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :id, :to_meter, :factor, :name
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def self.list
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # First get linear units
         
     | 
| 
      
 7 
     | 
    
         
            +
                  pointer_to_array = FFI::Pointer.new(Api::PJ_UNITS, Api.proj_list_units)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  result = Array.new
         
     | 
| 
      
 9 
     | 
    
         
            +
                  0.step do |i|
         
     | 
| 
      
 10 
     | 
    
         
            +
                    ellipse_info = Api::PJ_UNITS.new(pointer_to_array[i])
         
     | 
| 
      
 11 
     | 
    
         
            +
                    break if ellipse_info[:id].nil?
         
     | 
| 
      
 12 
     | 
    
         
            +
                    result << self.new(ellipse_info[:id], ellipse_info[:to_meter], ellipse_info[:factor], ellipse_info[:name])
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  # Now get angular linear units
         
     | 
| 
      
 16 
     | 
    
         
            +
                  if Api.method_defined?(:proj_list_angular_units)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    pointer_to_array = FFI::Pointer.new(Api::PJ_UNITS, Api.proj_list_angular_units)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    0.step do |i|
         
     | 
| 
      
 19 
     | 
    
         
            +
                      ellipse_info = Api::PJ_UNITS.new(pointer_to_array[i])
         
     | 
| 
      
 20 
     | 
    
         
            +
                      break result if ellipse_info[:id].nil?
         
     | 
| 
      
 21 
     | 
    
         
            +
                      result << self.new(ellipse_info[:id], ellipse_info[:to_meter], ellipse_info[:factor], ellipse_info[:name])
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                  result
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def self.get(id)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  self.list.find {|ellipsoid| ellipsoid.id == id}
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def initialize(id, to_meter, factor, name)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @id = id
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @to_meter = to_meter
         
     | 
| 
      
 34 
     | 
    
         
            +
                  @factor = factor
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @name = name
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def <=>(other)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  self.id <=> other.id
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def ==(other)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  self.id == other.id
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 47 
     | 
    
         
            +
                  self.id
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
                
         
     | 
| 
      
 50 
     | 
    
         
            +
                def inspect
         
     | 
| 
      
 51 
     | 
    
         
            +
                  "#<#{self.class} id=\"#{id}\", to_meter=\"#{to_meter}\", factor=\"#{factor}\", name=\"#{name}\">"
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
    
        data/proj4rb.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,31 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Gem::Specification.new do |spec|
         
     | 
| 
      
 2 
     | 
    
         
            +
              spec.name = 'proj4rb'
         
     | 
| 
      
 3 
     | 
    
         
            +
              spec.version = '2.0.0'
         
     | 
| 
      
 4 
     | 
    
         
            +
              spec.summary = 'Ruby bindings for the Proj.4 Carthographic Projection library'
         
     | 
| 
      
 5 
     | 
    
         
            +
              spec.description = <<-EOF
         
     | 
| 
      
 6 
     | 
    
         
            +
                Proj4rb is a ruby binding for the Proj.4 Carthographic Projection library, that supports conversions between a very large number of geographic coordinate systems and datumspec.
         
     | 
| 
      
 7 
     | 
    
         
            +
              EOF
         
     | 
| 
      
 8 
     | 
    
         
            +
              spec.platform = Gem::Platform::RUBY
         
     | 
| 
      
 9 
     | 
    
         
            +
              spec.authors = ['Guilhem Vellut', 'Jochen Topf', 'Charlie Savage']
         
     | 
| 
      
 10 
     | 
    
         
            +
              spec.homepage = 'https://github.com/cfis/proj4rb'
         
     | 
| 
      
 11 
     | 
    
         
            +
              spec.required_ruby_version = '>= 2.4.9'
         
     | 
| 
      
 12 
     | 
    
         
            +
              spec.license = 'MIT'
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              spec.requirements << 'Proj (Proj4) Library'
         
     | 
| 
      
 15 
     | 
    
         
            +
              spec.require_path = 'lib'
         
     | 
| 
      
 16 
     | 
    
         
            +
              spec.files = Dir['ChangeLog',
         
     | 
| 
      
 17 
     | 
    
         
            +
                               'Gemfile',
         
     | 
| 
      
 18 
     | 
    
         
            +
                               'MIT-LICENSE',
         
     | 
| 
      
 19 
     | 
    
         
            +
                               'proj4rb.gemspec',
         
     | 
| 
      
 20 
     | 
    
         
            +
                               'Rakefile',
         
     | 
| 
      
 21 
     | 
    
         
            +
                               'README.rdoc',
         
     | 
| 
      
 22 
     | 
    
         
            +
                               'lib/*.rb',
         
     | 
| 
      
 23 
     | 
    
         
            +
                               'test/*.rb']
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              spec.test_files = Dir["test/test_*.rb"]
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              spec.add_dependency "ffi"
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              spec.add_development_dependency('minitest')
         
     | 
| 
      
 30 
     | 
    
         
            +
              spec.add_development_dependency('yard')
         
     | 
| 
      
 31 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,82 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative './abstract_test'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            class ContextTest < AbstractTest
         
     | 
| 
      
 6 
     | 
    
         
            +
              def test_create
         
     | 
| 
      
 7 
     | 
    
         
            +
                context = Proj::Context.new
         
     | 
| 
      
 8 
     | 
    
         
            +
                assert(context.to_ptr)
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              def test_finalize
         
     | 
| 
      
 12 
     | 
    
         
            +
                500.times do
         
     | 
| 
      
 13 
     | 
    
         
            +
                  context = Proj::Context.new
         
     | 
| 
      
 14 
     | 
    
         
            +
                  assert(context.to_ptr)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  GC.start
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
                assert(true)
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              def test_one_per_thread
         
     | 
| 
      
 21 
     | 
    
         
            +
                context_1 = Proj::Context.current
         
     | 
| 
      
 22 
     | 
    
         
            +
                context_2 = Proj::Context.current
         
     | 
| 
      
 23 
     | 
    
         
            +
                assert_same(context_1, context_2)
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              def test_database_path
         
     | 
| 
      
 27 
     | 
    
         
            +
                refute_nil(Proj::Context.current.database_path)
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              def test_log_level
         
     | 
| 
      
 31 
     | 
    
         
            +
                assert_equal(:PJ_LOG_NONE, Proj::Context.current.log_level)
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              def test_set_log_level
         
     | 
| 
      
 35 
     | 
    
         
            +
                context = Proj::Context.new
         
     | 
| 
      
 36 
     | 
    
         
            +
                context.log_level = :PJ_LOG_ERROR
         
     | 
| 
      
 37 
     | 
    
         
            +
                assert_equal(:PJ_LOG_ERROR, context.log_level)
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              def test_invalid_database_path
         
     | 
| 
      
 41 
     | 
    
         
            +
                path = '/wrong'
         
     | 
| 
      
 42 
     | 
    
         
            +
                error = assert_raises(Proj::Error) do
         
     | 
| 
      
 43 
     | 
    
         
            +
                  Proj::Context.current.database_path = path
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
                # TODO - if you run this test on its own you get a useful error message, if you run all tests
         
     | 
| 
      
 46 
     | 
    
         
            +
                # at once you get a useless error message. Not sure what is causing the difference
         
     | 
| 
      
 47 
     | 
    
         
            +
                assert_match(/No such file or directory|generic error of unknown origin/, error.to_s)
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              def test_set_log_function
         
     | 
| 
      
 51 
     | 
    
         
            +
                context = Proj::Context.new
         
     | 
| 
      
 52 
     | 
    
         
            +
                called = false
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                data = FFI::MemoryPointer.new(:int)
         
     | 
| 
      
 55 
     | 
    
         
            +
                data.write_int(5)
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                context.set_log_function(data) do |pointer, int, message|
         
     | 
| 
      
 58 
     | 
    
         
            +
                  called = true
         
     | 
| 
      
 59 
     | 
    
         
            +
                  refute(pointer.null?)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  assert_equal(5, pointer.read_int)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  assert_equal(1, int)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  assert_equal('proj_context_set_database_path: Open of /wrong failed', message)
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                begin
         
     | 
| 
      
 66 
     | 
    
         
            +
                  context.database_path = '/wrong'
         
     | 
| 
      
 67 
     | 
    
         
            +
                rescue
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                assert(called)
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
              def test_use_proj4_init_rules
         
     | 
| 
      
 74 
     | 
    
         
            +
                refute(Proj::Context.current.use_proj4_init_rules)
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                Proj::Context.current.use_proj4_init_rules = true
         
     | 
| 
      
 77 
     | 
    
         
            +
                assert(Proj::Context.current.use_proj4_init_rules)
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                Proj::Context.current.use_proj4_init_rules = false
         
     | 
| 
      
 80 
     | 
    
         
            +
                refute(Proj::Context.current.use_proj4_init_rules)
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
            end
         
     |