rgeo 0.2.1 → 0.2.2
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/History.rdoc +9 -0
 - data/README.rdoc +8 -4
 - data/Version +1 -1
 - data/ext/geos_c_impl/extconf.rb +4 -0
 - data/ext/proj4_c_impl/extconf.rb +6 -0
 - data/lib/rgeo/cartesian/factory.rb +5 -1
 - data/lib/rgeo/coord_sys.rb +25 -6
 - data/lib/rgeo/coord_sys/cs/entities.rb +805 -0
 - data/lib/rgeo/coord_sys/cs/factories.rb +138 -0
 - data/lib/rgeo/coord_sys/cs/wkt_parser.rb +307 -0
 - data/lib/rgeo/coord_sys/proj4.rb +3 -0
 - data/lib/rgeo/coord_sys/srs_database/active_record_table.rb +112 -0
 - data/lib/rgeo/coord_sys/srs_database/interface.rb +112 -0
 - data/lib/rgeo/coord_sys/srs_database/proj4_data.rb +143 -0
 - data/lib/rgeo/coord_sys/srs_database/sr_org.rb +88 -0
 - data/lib/rgeo/coord_sys/srs_database/url_reader.rb +90 -0
 - data/lib/rgeo/feature/types.rb +11 -7
 - data/lib/rgeo/geos/factory.rb +6 -1
 - data/lib/rgeo/geos/impl_additions.rb +1 -1
 - data/lib/rgeo/geos/zm_impl.rb +1 -1
 - data/lib/rgeo/impl_helper/basic_geometry_methods.rb +1 -1
 - data/test/coord_sys/tc_active_record_table.rb +97 -0
 - data/test/coord_sys/tc_ogc_cs.rb +356 -0
 - data/test/coord_sys/tc_proj4_srs_data.rb +76 -0
 - data/test/coord_sys/tc_sr_org.rb +70 -0
 - data/test/coord_sys/tc_url_reader.rb +82 -0
 - data/test/geos/tc_polygon.rb +24 -0
 - metadata +21 -3
 
| 
         @@ -0,0 +1,138 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -----------------------------------------------------------------------------
         
     | 
| 
      
 2 
     | 
    
         
            +
            # 
         
     | 
| 
      
 3 
     | 
    
         
            +
            # OGC CS factory for RGeo
         
     | 
| 
      
 4 
     | 
    
         
            +
            # 
         
     | 
| 
      
 5 
     | 
    
         
            +
            # -----------------------------------------------------------------------------
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Copyright 2010 Daniel Azuma
         
     | 
| 
      
 7 
     | 
    
         
            +
            # 
         
     | 
| 
      
 8 
     | 
    
         
            +
            # All rights reserved.
         
     | 
| 
      
 9 
     | 
    
         
            +
            # 
         
     | 
| 
      
 10 
     | 
    
         
            +
            # Redistribution and use in source and binary forms, with or without
         
     | 
| 
      
 11 
     | 
    
         
            +
            # modification, are permitted provided that the following conditions are met:
         
     | 
| 
      
 12 
     | 
    
         
            +
            # 
         
     | 
| 
      
 13 
     | 
    
         
            +
            # * Redistributions of source code must retain the above copyright notice,
         
     | 
| 
      
 14 
     | 
    
         
            +
            #   this list of conditions and the following disclaimer.
         
     | 
| 
      
 15 
     | 
    
         
            +
            # * Redistributions in binary form must reproduce the above copyright notice,
         
     | 
| 
      
 16 
     | 
    
         
            +
            #   this list of conditions and the following disclaimer in the documentation
         
     | 
| 
      
 17 
     | 
    
         
            +
            #   and/or other materials provided with the distribution.
         
     | 
| 
      
 18 
     | 
    
         
            +
            # * Neither the name of the copyright holder, nor the names of any other
         
     | 
| 
      
 19 
     | 
    
         
            +
            #   contributors to this software, may be used to endorse or promote products
         
     | 
| 
      
 20 
     | 
    
         
            +
            #   derived from this software without specific prior written permission.
         
     | 
| 
      
 21 
     | 
    
         
            +
            # 
         
     | 
| 
      
 22 
     | 
    
         
            +
            # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
         
     | 
| 
      
 23 
     | 
    
         
            +
            # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
         
     | 
| 
      
 24 
     | 
    
         
            +
            # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
         
     | 
| 
      
 25 
     | 
    
         
            +
            # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
         
     | 
| 
      
 26 
     | 
    
         
            +
            # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
         
     | 
| 
      
 27 
     | 
    
         
            +
            # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
         
     | 
| 
      
 28 
     | 
    
         
            +
            # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
         
     | 
| 
      
 29 
     | 
    
         
            +
            # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
         
     | 
| 
      
 30 
     | 
    
         
            +
            # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
         
     | 
| 
      
 31 
     | 
    
         
            +
            # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
         
     | 
| 
      
 32 
     | 
    
         
            +
            # POSSIBILITY OF SUCH DAMAGE.
         
     | 
| 
      
 33 
     | 
    
         
            +
            # -----------------------------------------------------------------------------
         
     | 
| 
      
 34 
     | 
    
         
            +
            ;
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            module RGeo
         
     | 
| 
      
 38 
     | 
    
         
            +
              
         
     | 
| 
      
 39 
     | 
    
         
            +
              module CoordSys
         
     | 
| 
      
 40 
     | 
    
         
            +
                
         
     | 
| 
      
 41 
     | 
    
         
            +
                
         
     | 
| 
      
 42 
     | 
    
         
            +
                # This module contains an implementation of the CS (coordinate
         
     | 
| 
      
 43 
     | 
    
         
            +
                # systems) package of the OGC Coordinate Transform spec. It contains
         
     | 
| 
      
 44 
     | 
    
         
            +
                # classes for representing ellipsoids, datums, coordinate systems,
         
     | 
| 
      
 45 
     | 
    
         
            +
                # and other related concepts, as well as a parser for the WKT format
         
     | 
| 
      
 46 
     | 
    
         
            +
                # for specifying coordinate systems.
         
     | 
| 
      
 47 
     | 
    
         
            +
                # 
         
     | 
| 
      
 48 
     | 
    
         
            +
                # Generally, the easiest way to create coordinate system objects is
         
     | 
| 
      
 49 
     | 
    
         
            +
                # to use RGeo::CoordSys::CS.create_from_wkt, which parses the WKT
         
     | 
| 
      
 50 
     | 
    
         
            +
                # format. This and other methods of the FactoryMethods module are all
         
     | 
| 
      
 51 
     | 
    
         
            +
                # available as convenient module functions on the CS module.
         
     | 
| 
      
 52 
     | 
    
         
            +
                # 
         
     | 
| 
      
 53 
     | 
    
         
            +
                # Almost the entire spec is implemented here. Currently missing are:
         
     | 
| 
      
 54 
     | 
    
         
            +
                # 
         
     | 
| 
      
 55 
     | 
    
         
            +
                # * XML format is not implemented. We're assuming that WKT is the
         
     | 
| 
      
 56 
     | 
    
         
            +
                #   preferred format.
         
     | 
| 
      
 57 
     | 
    
         
            +
                # * The PT and CT packages are not implemented.
         
     | 
| 
      
 58 
     | 
    
         
            +
                # * FittedCoordinateSystem is not implemented.
         
     | 
| 
      
 59 
     | 
    
         
            +
                
         
     | 
| 
      
 60 
     | 
    
         
            +
                module CS
         
     | 
| 
      
 61 
     | 
    
         
            +
                  
         
     | 
| 
      
 62 
     | 
    
         
            +
                  
         
     | 
| 
      
 63 
     | 
    
         
            +
                  module FactoryMethods
         
     | 
| 
      
 64 
     | 
    
         
            +
                    
         
     | 
| 
      
 65 
     | 
    
         
            +
                    def create_compound_coordinate_system(name_, head_, tail_)
         
     | 
| 
      
 66 
     | 
    
         
            +
                      CompoundCoordinateSystem.create(name_, head_, tail_)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    end
         
     | 
| 
      
 68 
     | 
    
         
            +
                    
         
     | 
| 
      
 69 
     | 
    
         
            +
                    def create_ellipsoid(name_, semi_major_axis_, semi_minor_axis_, linear_unit_)
         
     | 
| 
      
 70 
     | 
    
         
            +
                      Ellipsoid.create_ellipsoid(name_, semi_major_axis_, semi_minor_axis_, linear_unit_)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    end
         
     | 
| 
      
 72 
     | 
    
         
            +
                    
         
     | 
| 
      
 73 
     | 
    
         
            +
                    def create_flattened_sphere(name_, semi_major_axis_, inverse_flattening_, linear_unit_)
         
     | 
| 
      
 74 
     | 
    
         
            +
                      Ellipsoid.create_flattened_sphere(name_, semi_major_axis_, inverse_flattening_, linear_unit_)
         
     | 
| 
      
 75 
     | 
    
         
            +
                    end
         
     | 
| 
      
 76 
     | 
    
         
            +
                    
         
     | 
| 
      
 77 
     | 
    
         
            +
                    def create_from_wkt(str_)
         
     | 
| 
      
 78 
     | 
    
         
            +
                      WKTParser.new(str_).parse
         
     | 
| 
      
 79 
     | 
    
         
            +
                    end
         
     | 
| 
      
 80 
     | 
    
         
            +
                    
         
     | 
| 
      
 81 
     | 
    
         
            +
                    def create_geographic_coordinate_system(name_, angular_unit_, horizontal_datum_, prime_meridian_, axis0_, axis1_)
         
     | 
| 
      
 82 
     | 
    
         
            +
                      GeographicCoordinateSystem.create(name_, angular_unit_, horizontal_datum_, prime_meridian_, axis0_, axis1_)
         
     | 
| 
      
 83 
     | 
    
         
            +
                    end
         
     | 
| 
      
 84 
     | 
    
         
            +
                    
         
     | 
| 
      
 85 
     | 
    
         
            +
                    def create_horizontal_datum(name_, horizontal_datum_type_, ellipsoid_, to_wgs84_)
         
     | 
| 
      
 86 
     | 
    
         
            +
                      HorizontalDatum.create(name_, horizontal_datum_type_, ellipsoid_, to_wgs84_)
         
     | 
| 
      
 87 
     | 
    
         
            +
                    end
         
     | 
| 
      
 88 
     | 
    
         
            +
                    
         
     | 
| 
      
 89 
     | 
    
         
            +
                    def create_local_coordinate_system(name_, datum_, unit_, axes_)
         
     | 
| 
      
 90 
     | 
    
         
            +
                      LocalCoordinateSystem.create(name_, datum_, unit_, axes_)
         
     | 
| 
      
 91 
     | 
    
         
            +
                    end
         
     | 
| 
      
 92 
     | 
    
         
            +
                    
         
     | 
| 
      
 93 
     | 
    
         
            +
                    def create_local_datum(name_, local_datum_type_)
         
     | 
| 
      
 94 
     | 
    
         
            +
                      LocalDatum.create(name, local_datum_type_)
         
     | 
| 
      
 95 
     | 
    
         
            +
                    end
         
     | 
| 
      
 96 
     | 
    
         
            +
                    
         
     | 
| 
      
 97 
     | 
    
         
            +
                    def create_prime_meridian(name_, angular_unit_, longitude_)
         
     | 
| 
      
 98 
     | 
    
         
            +
                      PrimeMeridian.create(name, angular_unit_, longitude_)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    end
         
     | 
| 
      
 100 
     | 
    
         
            +
                    
         
     | 
| 
      
 101 
     | 
    
         
            +
                    def create_projected_coordinate_system(name_, gcs_, projection_, linear_unit_, axis0_, axis1_)
         
     | 
| 
      
 102 
     | 
    
         
            +
                      ProjectedCoordinateSystem.create(name_, gcs_, projection_, linear_unit_, axis0_, axis1_)
         
     | 
| 
      
 103 
     | 
    
         
            +
                    end
         
     | 
| 
      
 104 
     | 
    
         
            +
                    
         
     | 
| 
      
 105 
     | 
    
         
            +
                    def create_projection(name_, wkt_projection_class_, parameters_)
         
     | 
| 
      
 106 
     | 
    
         
            +
                      Projection.create(name_, wkt_projection_class_, parameters_)
         
     | 
| 
      
 107 
     | 
    
         
            +
                    end
         
     | 
| 
      
 108 
     | 
    
         
            +
                    
         
     | 
| 
      
 109 
     | 
    
         
            +
                    def create_vertical_coordinate_system(name_, vertical_datum_, vertical_unit_, axis_)
         
     | 
| 
      
 110 
     | 
    
         
            +
                      VerticalCoordinateSystem.create(name_, vertical_datum_, vertical_unit_, axis_)
         
     | 
| 
      
 111 
     | 
    
         
            +
                    end
         
     | 
| 
      
 112 
     | 
    
         
            +
                    
         
     | 
| 
      
 113 
     | 
    
         
            +
                    def create_vertical_datum(name_, vertical_datum_type_)
         
     | 
| 
      
 114 
     | 
    
         
            +
                      VerticalDatum.create(name_, vertical_datum_type_)
         
     | 
| 
      
 115 
     | 
    
         
            +
                    end
         
     | 
| 
      
 116 
     | 
    
         
            +
                    
         
     | 
| 
      
 117 
     | 
    
         
            +
                  end
         
     | 
| 
      
 118 
     | 
    
         
            +
                  
         
     | 
| 
      
 119 
     | 
    
         
            +
                  
         
     | 
| 
      
 120 
     | 
    
         
            +
                  class CoordinateSystemFactory
         
     | 
| 
      
 121 
     | 
    
         
            +
                    
         
     | 
| 
      
 122 
     | 
    
         
            +
                    include FactoryMethods
         
     | 
| 
      
 123 
     | 
    
         
            +
                    
         
     | 
| 
      
 124 
     | 
    
         
            +
                  end
         
     | 
| 
      
 125 
     | 
    
         
            +
                  
         
     | 
| 
      
 126 
     | 
    
         
            +
                  
         
     | 
| 
      
 127 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 128 
     | 
    
         
            +
                    
         
     | 
| 
      
 129 
     | 
    
         
            +
                    include FactoryMethods
         
     | 
| 
      
 130 
     | 
    
         
            +
                    
         
     | 
| 
      
 131 
     | 
    
         
            +
                  end
         
     | 
| 
      
 132 
     | 
    
         
            +
                  
         
     | 
| 
      
 133 
     | 
    
         
            +
                  
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
      
 135 
     | 
    
         
            +
                
         
     | 
| 
      
 136 
     | 
    
         
            +
              end
         
     | 
| 
      
 137 
     | 
    
         
            +
              
         
     | 
| 
      
 138 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,307 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -----------------------------------------------------------------------------
         
     | 
| 
      
 2 
     | 
    
         
            +
            # 
         
     | 
| 
      
 3 
     | 
    
         
            +
            # OGC CS wkt parser for RGeo
         
     | 
| 
      
 4 
     | 
    
         
            +
            # 
         
     | 
| 
      
 5 
     | 
    
         
            +
            # -----------------------------------------------------------------------------
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Copyright 2010 Daniel Azuma
         
     | 
| 
      
 7 
     | 
    
         
            +
            # 
         
     | 
| 
      
 8 
     | 
    
         
            +
            # All rights reserved.
         
     | 
| 
      
 9 
     | 
    
         
            +
            # 
         
     | 
| 
      
 10 
     | 
    
         
            +
            # Redistribution and use in source and binary forms, with or without
         
     | 
| 
      
 11 
     | 
    
         
            +
            # modification, are permitted provided that the following conditions are met:
         
     | 
| 
      
 12 
     | 
    
         
            +
            # 
         
     | 
| 
      
 13 
     | 
    
         
            +
            # * Redistributions of source code must retain the above copyright notice,
         
     | 
| 
      
 14 
     | 
    
         
            +
            #   this list of conditions and the following disclaimer.
         
     | 
| 
      
 15 
     | 
    
         
            +
            # * Redistributions in binary form must reproduce the above copyright notice,
         
     | 
| 
      
 16 
     | 
    
         
            +
            #   this list of conditions and the following disclaimer in the documentation
         
     | 
| 
      
 17 
     | 
    
         
            +
            #   and/or other materials provided with the distribution.
         
     | 
| 
      
 18 
     | 
    
         
            +
            # * Neither the name of the copyright holder, nor the names of any other
         
     | 
| 
      
 19 
     | 
    
         
            +
            #   contributors to this software, may be used to endorse or promote products
         
     | 
| 
      
 20 
     | 
    
         
            +
            #   derived from this software without specific prior written permission.
         
     | 
| 
      
 21 
     | 
    
         
            +
            # 
         
     | 
| 
      
 22 
     | 
    
         
            +
            # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
         
     | 
| 
      
 23 
     | 
    
         
            +
            # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
         
     | 
| 
      
 24 
     | 
    
         
            +
            # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
         
     | 
| 
      
 25 
     | 
    
         
            +
            # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
         
     | 
| 
      
 26 
     | 
    
         
            +
            # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
         
     | 
| 
      
 27 
     | 
    
         
            +
            # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
         
     | 
| 
      
 28 
     | 
    
         
            +
            # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
         
     | 
| 
      
 29 
     | 
    
         
            +
            # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
         
     | 
| 
      
 30 
     | 
    
         
            +
            # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
         
     | 
| 
      
 31 
     | 
    
         
            +
            # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
         
     | 
| 
      
 32 
     | 
    
         
            +
            # POSSIBILITY OF SUCH DAMAGE.
         
     | 
| 
      
 33 
     | 
    
         
            +
            # -----------------------------------------------------------------------------
         
     | 
| 
      
 34 
     | 
    
         
            +
            ;
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            module RGeo
         
     | 
| 
      
 38 
     | 
    
         
            +
              
         
     | 
| 
      
 39 
     | 
    
         
            +
              module CoordSys
         
     | 
| 
      
 40 
     | 
    
         
            +
                
         
     | 
| 
      
 41 
     | 
    
         
            +
                
         
     | 
| 
      
 42 
     | 
    
         
            +
                module CS
         
     | 
| 
      
 43 
     | 
    
         
            +
                  
         
     | 
| 
      
 44 
     | 
    
         
            +
                  
         
     | 
| 
      
 45 
     | 
    
         
            +
                  class WKTParser  # :nodoc:
         
     | 
| 
      
 46 
     | 
    
         
            +
                    
         
     | 
| 
      
 47 
     | 
    
         
            +
                    def initialize(str_)
         
     | 
| 
      
 48 
     | 
    
         
            +
                      @scanner = ::StringScanner.new(str_)
         
     | 
| 
      
 49 
     | 
    
         
            +
                      next_token
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                    
         
     | 
| 
      
 52 
     | 
    
         
            +
                    
         
     | 
| 
      
 53 
     | 
    
         
            +
                    def parse(containing_type_=nil)
         
     | 
| 
      
 54 
     | 
    
         
            +
                      if @cur_token.kind_of?(QuotedString) ||
         
     | 
| 
      
 55 
     | 
    
         
            +
                          @cur_token.kind_of?(::Numeric) ||
         
     | 
| 
      
 56 
     | 
    
         
            +
                          (containing_type_ == 'AXIS' && @cur_token.kind_of?(TypeString))
         
     | 
| 
      
 57 
     | 
    
         
            +
                        value_ = @cur_token
         
     | 
| 
      
 58 
     | 
    
         
            +
                        next_token
         
     | 
| 
      
 59 
     | 
    
         
            +
                        return value_
         
     | 
| 
      
 60 
     | 
    
         
            +
                      end
         
     | 
| 
      
 61 
     | 
    
         
            +
                      unless @cur_token.kind_of?(TypeString)
         
     | 
| 
      
 62 
     | 
    
         
            +
                        raise Error::ParseError("Found token #{@cur_token} when we expected a value")
         
     | 
| 
      
 63 
     | 
    
         
            +
                      end
         
     | 
| 
      
 64 
     | 
    
         
            +
                      type_ = @cur_token
         
     | 
| 
      
 65 
     | 
    
         
            +
                      next_token
         
     | 
| 
      
 66 
     | 
    
         
            +
                      consume_token_type(:begin)
         
     | 
| 
      
 67 
     | 
    
         
            +
                      args_ = ArgumentList.new
         
     | 
| 
      
 68 
     | 
    
         
            +
                      args_ << parse(type_)
         
     | 
| 
      
 69 
     | 
    
         
            +
                      loop do
         
     | 
| 
      
 70 
     | 
    
         
            +
                        break unless @cur_token == :comma
         
     | 
| 
      
 71 
     | 
    
         
            +
                        next_token
         
     | 
| 
      
 72 
     | 
    
         
            +
                        args_ << parse(type_)
         
     | 
| 
      
 73 
     | 
    
         
            +
                      end
         
     | 
| 
      
 74 
     | 
    
         
            +
                      consume_token_type(:end)
         
     | 
| 
      
 75 
     | 
    
         
            +
                      obj_ = nil
         
     | 
| 
      
 76 
     | 
    
         
            +
                      case type_
         
     | 
| 
      
 77 
     | 
    
         
            +
                      when 'AUTHORITY'
         
     | 
| 
      
 78 
     | 
    
         
            +
                        obj_ = AuthorityClause.new(args_.shift(QuotedString), args_.shift(QuotedString))
         
     | 
| 
      
 79 
     | 
    
         
            +
                      when 'AXIS'
         
     | 
| 
      
 80 
     | 
    
         
            +
                        obj_ = AxisInfo.create(args_.shift(QuotedString), args_.shift(TypeString))
         
     | 
| 
      
 81 
     | 
    
         
            +
                      when 'TOWGS84'
         
     | 
| 
      
 82 
     | 
    
         
            +
                        bursa_wolf_params_ = args_.find_all(::Numeric)
         
     | 
| 
      
 83 
     | 
    
         
            +
                        unless bursa_wolf_params_.size == 7
         
     | 
| 
      
 84 
     | 
    
         
            +
                          raise Error::ParseError("Expected 7 Bursa Wolf parameters but found #{bursa_wolf_params_.size}")
         
     | 
| 
      
 85 
     | 
    
         
            +
                        end
         
     | 
| 
      
 86 
     | 
    
         
            +
                        obj_ = WGS84ConversionInfo.create(*bursa_wolf_params_)
         
     | 
| 
      
 87 
     | 
    
         
            +
                      when 'UNIT'
         
     | 
| 
      
 88 
     | 
    
         
            +
                        case containing_type_
         
     | 
| 
      
 89 
     | 
    
         
            +
                        when 'GEOCCS', 'VERT_CS', 'PROJCS', 'SPHEROID'
         
     | 
| 
      
 90 
     | 
    
         
            +
                          klass_ = LinearUnit
         
     | 
| 
      
 91 
     | 
    
         
            +
                        when 'GEOGCS'
         
     | 
| 
      
 92 
     | 
    
         
            +
                          klass_ = AngularUnit
         
     | 
| 
      
 93 
     | 
    
         
            +
                        else
         
     | 
| 
      
 94 
     | 
    
         
            +
                          klass_ = Unit
         
     | 
| 
      
 95 
     | 
    
         
            +
                        end
         
     | 
| 
      
 96 
     | 
    
         
            +
                        obj_ = klass_.create(args_.shift(QuotedString), args_.shift(::Numeric), *args_.find_first(AuthorityClause).to_a)
         
     | 
| 
      
 97 
     | 
    
         
            +
                      when 'PARAMETER'
         
     | 
| 
      
 98 
     | 
    
         
            +
                        obj_ = ProjectionParameter.create(args_.shift(QuotedString), args_.shift(::Numeric))
         
     | 
| 
      
 99 
     | 
    
         
            +
                      when 'PRIMEM'
         
     | 
| 
      
 100 
     | 
    
         
            +
                        obj_ = PrimeMeridian.create(args_.shift(QuotedString), nil, args_.shift(::Numeric), *args_.find_first(AuthorityClause).to_a)
         
     | 
| 
      
 101 
     | 
    
         
            +
                      when 'SPHEROID'
         
     | 
| 
      
 102 
     | 
    
         
            +
                        obj_ = Ellipsoid.create_flattened_sphere(args_.shift(QuotedString), args_.shift(::Numeric), args_.shift(::Numeric), args_.find_first(LinearUnit), *args_.find_first(AuthorityClause).to_a)
         
     | 
| 
      
 103 
     | 
    
         
            +
                      when 'PROJECTION'
         
     | 
| 
      
 104 
     | 
    
         
            +
                        name_ = args_.shift(QuotedString)
         
     | 
| 
      
 105 
     | 
    
         
            +
                        obj_ = Projection.create(name_, name_, args_.find_all(ProjectionParameter), *args_.find_first(AuthorityClause).to_a)
         
     | 
| 
      
 106 
     | 
    
         
            +
                      when 'DATUM'
         
     | 
| 
      
 107 
     | 
    
         
            +
                        name_ = args_.shift(QuotedString)
         
     | 
| 
      
 108 
     | 
    
         
            +
                        ellipsoid_ = args_.find_first(Ellipsoid)
         
     | 
| 
      
 109 
     | 
    
         
            +
                        to_wgs84_ = args_.find_first(WGS84ConversionInfo)
         
     | 
| 
      
 110 
     | 
    
         
            +
                        obj_ = HorizontalDatum.create(name_, HD_GEOCENTRIC, ellipsoid_, to_wgs84_, *args_.find_first(AuthorityClause).to_a)
         
     | 
| 
      
 111 
     | 
    
         
            +
                      when 'VERT_DATUM'
         
     | 
| 
      
 112 
     | 
    
         
            +
                        obj_ = VerticalDatum.create(args_.shift(QuotedString), args_.shift(::Numeric), *args_.find_first(AuthorityClause).to_a)
         
     | 
| 
      
 113 
     | 
    
         
            +
                      when 'LOCAL_DATUM'
         
     | 
| 
      
 114 
     | 
    
         
            +
                        obj_ = LocalDatum.create(args_.shift(QuotedString), args_.shift(::Numeric), *args_.find_first(AuthorityClause).to_a)
         
     | 
| 
      
 115 
     | 
    
         
            +
                      when 'COMPD_CS'
         
     | 
| 
      
 116 
     | 
    
         
            +
                        obj_ = CompoundCoordinateSystem.create(args_.shift(QuotedString), args_.shift(CoordinateSystem), args_.shift(CoordinateSystem), *args_.find_first(AuthorityClause).to_a)
         
     | 
| 
      
 117 
     | 
    
         
            +
                      when 'LOCAL_CS'
         
     | 
| 
      
 118 
     | 
    
         
            +
                        name_ = args_.shift(QuotedString)
         
     | 
| 
      
 119 
     | 
    
         
            +
                        local_datum_ = args_.find_first(LocalDatum)
         
     | 
| 
      
 120 
     | 
    
         
            +
                        unit_ = args_.find_first(Unit)
         
     | 
| 
      
 121 
     | 
    
         
            +
                        axes_ = args_.find_all(AxisInfo)
         
     | 
| 
      
 122 
     | 
    
         
            +
                        unless axes_.size > 0
         
     | 
| 
      
 123 
     | 
    
         
            +
                          raise Error::ParseError("Expected at least one AXIS in a LOCAL_CS")
         
     | 
| 
      
 124 
     | 
    
         
            +
                        end
         
     | 
| 
      
 125 
     | 
    
         
            +
                        obj_ = LocalCoordinateSystem.create(name_, local_datum_, unit_, axes_, *args_.find_first(AuthorityClause).to_a)
         
     | 
| 
      
 126 
     | 
    
         
            +
                      when 'GEOCCS'
         
     | 
| 
      
 127 
     | 
    
         
            +
                        name_ = args_.shift(QuotedString)
         
     | 
| 
      
 128 
     | 
    
         
            +
                        horizontal_datum_ = args_.find_first(HorizontalDatum)
         
     | 
| 
      
 129 
     | 
    
         
            +
                        prime_meridian_ = args_.find_first(PrimeMeridian)
         
     | 
| 
      
 130 
     | 
    
         
            +
                        linear_unit_ = args_.find_first(LinearUnit)
         
     | 
| 
      
 131 
     | 
    
         
            +
                        axes_ = args_.find_all(AxisInfo)
         
     | 
| 
      
 132 
     | 
    
         
            +
                        unless axes_.size == 0 || axes_.size == 3
         
     | 
| 
      
 133 
     | 
    
         
            +
                          raise Error::ParseError("GEOCCS must contain either 0 or 3 AXIS parameters")
         
     | 
| 
      
 134 
     | 
    
         
            +
                        end
         
     | 
| 
      
 135 
     | 
    
         
            +
                        obj_ = GeocentricCoordinateSystem.create(name_, horizontal_datum_, prime_meridian_, linear_unit_, axes_[0], axes_[1], axes_[2], *args_.find_first(AuthorityClause).to_a)
         
     | 
| 
      
 136 
     | 
    
         
            +
                      when 'VERT_CS'
         
     | 
| 
      
 137 
     | 
    
         
            +
                        name_ = args_.shift(QuotedString)
         
     | 
| 
      
 138 
     | 
    
         
            +
                        vertical_datum_ = args_.find_first(VerticalDatum)
         
     | 
| 
      
 139 
     | 
    
         
            +
                        linear_unit_ = args_.find_first(LinearUnit)
         
     | 
| 
      
 140 
     | 
    
         
            +
                        axis_ = args_.find_first(AxisInfo)
         
     | 
| 
      
 141 
     | 
    
         
            +
                        obj_ = VerticalCoordinateSystem.create(name_, vertical_datum_, linear_unit_, axis_, *args_.find_first(AuthorityClause).to_a)
         
     | 
| 
      
 142 
     | 
    
         
            +
                      when 'GEOGCS'
         
     | 
| 
      
 143 
     | 
    
         
            +
                        name_ = args_.shift(QuotedString)
         
     | 
| 
      
 144 
     | 
    
         
            +
                        horizontal_datum_ = args_.find_first(HorizontalDatum)
         
     | 
| 
      
 145 
     | 
    
         
            +
                        prime_meridian_ = args_.find_first(PrimeMeridian)
         
     | 
| 
      
 146 
     | 
    
         
            +
                        angular_unit_ = args_.find_first(AngularUnit)
         
     | 
| 
      
 147 
     | 
    
         
            +
                        axes_ = args_.find_all(AxisInfo)
         
     | 
| 
      
 148 
     | 
    
         
            +
                        unless axes_.size == 0 || axes_.size == 2
         
     | 
| 
      
 149 
     | 
    
         
            +
                          raise Error::ParseError("GEOGCS must contain either 0 or 2 AXIS parameters")
         
     | 
| 
      
 150 
     | 
    
         
            +
                        end
         
     | 
| 
      
 151 
     | 
    
         
            +
                        obj_ = GeographicCoordinateSystem.create(name_, angular_unit_, horizontal_datum_, prime_meridian_, axes_[0], axes_[1], *args_.find_first(AuthorityClause).to_a)
         
     | 
| 
      
 152 
     | 
    
         
            +
                      when 'PROJCS'
         
     | 
| 
      
 153 
     | 
    
         
            +
                        name_ = args_.shift(QuotedString)
         
     | 
| 
      
 154 
     | 
    
         
            +
                        geographic_coordinate_system_ = args_.find_first(GeographicCoordinateSystem)
         
     | 
| 
      
 155 
     | 
    
         
            +
                        projection_ = args_.find_first(Projection)
         
     | 
| 
      
 156 
     | 
    
         
            +
                        parameters_ = args_.find_all(ProjectionParameter)
         
     | 
| 
      
 157 
     | 
    
         
            +
                        projection_.instance_variable_get(:@parameters).concat(parameters_)
         
     | 
| 
      
 158 
     | 
    
         
            +
                        linear_unit_ = args_.find_first(LinearUnit)
         
     | 
| 
      
 159 
     | 
    
         
            +
                        axes_ = args_.find_all(AxisInfo)
         
     | 
| 
      
 160 
     | 
    
         
            +
                        unless axes_.size == 0 || axes_.size == 2
         
     | 
| 
      
 161 
     | 
    
         
            +
                          raise Error::ParseError("PROJCS must contain either 0 or 2 AXIS parameters")
         
     | 
| 
      
 162 
     | 
    
         
            +
                        end
         
     | 
| 
      
 163 
     | 
    
         
            +
                        obj_ = ProjectedCoordinateSystem.create(name_, geographic_coordinate_system_, projection_, linear_unit_, axes_[0], axes_[1], *args_.find_first(AuthorityClause).to_a)
         
     | 
| 
      
 164 
     | 
    
         
            +
                      else
         
     | 
| 
      
 165 
     | 
    
         
            +
                        raise Error::ParseError, "Unrecognized type: #{type_}"
         
     | 
| 
      
 166 
     | 
    
         
            +
                      end
         
     | 
| 
      
 167 
     | 
    
         
            +
                      args_.assert_empty
         
     | 
| 
      
 168 
     | 
    
         
            +
                      obj_
         
     | 
| 
      
 169 
     | 
    
         
            +
                    end
         
     | 
| 
      
 170 
     | 
    
         
            +
                    
         
     | 
| 
      
 171 
     | 
    
         
            +
                    
         
     | 
| 
      
 172 
     | 
    
         
            +
                    def consume_token_type(type_)  # :nodoc:
         
     | 
| 
      
 173 
     | 
    
         
            +
                      expect_token_type(type_)
         
     | 
| 
      
 174 
     | 
    
         
            +
                      tok_ = @cur_token
         
     | 
| 
      
 175 
     | 
    
         
            +
                      next_token
         
     | 
| 
      
 176 
     | 
    
         
            +
                      tok_
         
     | 
| 
      
 177 
     | 
    
         
            +
                    end
         
     | 
| 
      
 178 
     | 
    
         
            +
                    
         
     | 
| 
      
 179 
     | 
    
         
            +
                    def expect_token_type(type_)  # :nodoc:
         
     | 
| 
      
 180 
     | 
    
         
            +
                      unless type_ === @cur_token
         
     | 
| 
      
 181 
     | 
    
         
            +
                        raise Error::ParseError, "#{type_.inspect} expected but #{@cur_token.inspect} found."
         
     | 
| 
      
 182 
     | 
    
         
            +
                      end
         
     | 
| 
      
 183 
     | 
    
         
            +
                    end
         
     | 
| 
      
 184 
     | 
    
         
            +
                    
         
     | 
| 
      
 185 
     | 
    
         
            +
                    def next_token  # :nodoc:
         
     | 
| 
      
 186 
     | 
    
         
            +
                      @scanner.skip(/\s+/)
         
     | 
| 
      
 187 
     | 
    
         
            +
                      case @scanner.peek(1)
         
     | 
| 
      
 188 
     | 
    
         
            +
                      when '"'
         
     | 
| 
      
 189 
     | 
    
         
            +
                        @scanner.getch
         
     | 
| 
      
 190 
     | 
    
         
            +
                        @cur_token = QuotedString.new(@scanner.scan(/[^"]*/))
         
     | 
| 
      
 191 
     | 
    
         
            +
                        @scanner.getch
         
     | 
| 
      
 192 
     | 
    
         
            +
                      when ','
         
     | 
| 
      
 193 
     | 
    
         
            +
                        @scanner.getch
         
     | 
| 
      
 194 
     | 
    
         
            +
                        @cur_token = :comma
         
     | 
| 
      
 195 
     | 
    
         
            +
                      when '(','['
         
     | 
| 
      
 196 
     | 
    
         
            +
                        @scanner.getch
         
     | 
| 
      
 197 
     | 
    
         
            +
                        @cur_token = :begin
         
     | 
| 
      
 198 
     | 
    
         
            +
                      when ']',')'
         
     | 
| 
      
 199 
     | 
    
         
            +
                        @scanner.getch
         
     | 
| 
      
 200 
     | 
    
         
            +
                        @cur_token = :end
         
     | 
| 
      
 201 
     | 
    
         
            +
                      when /[a-zA-Z]/
         
     | 
| 
      
 202 
     | 
    
         
            +
                        @cur_token = TypeString.new(@scanner.scan(/[a-zA-Z]\w*/))
         
     | 
| 
      
 203 
     | 
    
         
            +
                      when '', nil
         
     | 
| 
      
 204 
     | 
    
         
            +
                        @cur_token = nil
         
     | 
| 
      
 205 
     | 
    
         
            +
                      else
         
     | 
| 
      
 206 
     | 
    
         
            +
                        @scanner.scan_until(/[^\s\(\)\[\],"]+/)
         
     | 
| 
      
 207 
     | 
    
         
            +
                        token_ = @scanner.matched
         
     | 
| 
      
 208 
     | 
    
         
            +
                        if token_ =~ /^[-+]?(\d+(\.\d*)?|\.\d+)(e[-+]?\d+)?$/
         
     | 
| 
      
 209 
     | 
    
         
            +
                          @cur_token = token_.to_f
         
     | 
| 
      
 210 
     | 
    
         
            +
                        else
         
     | 
| 
      
 211 
     | 
    
         
            +
                          raise Error::ParseError, "Bad token: #{token_.inspect}"
         
     | 
| 
      
 212 
     | 
    
         
            +
                        end
         
     | 
| 
      
 213 
     | 
    
         
            +
                      end
         
     | 
| 
      
 214 
     | 
    
         
            +
                      @cur_token
         
     | 
| 
      
 215 
     | 
    
         
            +
                    end
         
     | 
| 
      
 216 
     | 
    
         
            +
                    
         
     | 
| 
      
 217 
     | 
    
         
            +
                    def cur_token  # :nodoc:
         
     | 
| 
      
 218 
     | 
    
         
            +
                      @cur_token
         
     | 
| 
      
 219 
     | 
    
         
            +
                    end
         
     | 
| 
      
 220 
     | 
    
         
            +
                    
         
     | 
| 
      
 221 
     | 
    
         
            +
                    
         
     | 
| 
      
 222 
     | 
    
         
            +
                    class QuotedString < ::String  # :nodoc:
         
     | 
| 
      
 223 
     | 
    
         
            +
                    end
         
     | 
| 
      
 224 
     | 
    
         
            +
                    
         
     | 
| 
      
 225 
     | 
    
         
            +
                    class TypeString < ::String  # :nodoc:
         
     | 
| 
      
 226 
     | 
    
         
            +
                    end
         
     | 
| 
      
 227 
     | 
    
         
            +
                    
         
     | 
| 
      
 228 
     | 
    
         
            +
                    class AuthorityClause  # :nodoc:
         
     | 
| 
      
 229 
     | 
    
         
            +
                      
         
     | 
| 
      
 230 
     | 
    
         
            +
                      def initialize(name_, code_)
         
     | 
| 
      
 231 
     | 
    
         
            +
                        @name = name_
         
     | 
| 
      
 232 
     | 
    
         
            +
                        @code = code_
         
     | 
| 
      
 233 
     | 
    
         
            +
                      end
         
     | 
| 
      
 234 
     | 
    
         
            +
                      
         
     | 
| 
      
 235 
     | 
    
         
            +
                      def to_a
         
     | 
| 
      
 236 
     | 
    
         
            +
                        [@name, @code]
         
     | 
| 
      
 237 
     | 
    
         
            +
                      end
         
     | 
| 
      
 238 
     | 
    
         
            +
                      
         
     | 
| 
      
 239 
     | 
    
         
            +
                    end
         
     | 
| 
      
 240 
     | 
    
         
            +
                    
         
     | 
| 
      
 241 
     | 
    
         
            +
                    
         
     | 
| 
      
 242 
     | 
    
         
            +
                    class ArgumentList  # :nodoc:
         
     | 
| 
      
 243 
     | 
    
         
            +
                      
         
     | 
| 
      
 244 
     | 
    
         
            +
                      def initialize
         
     | 
| 
      
 245 
     | 
    
         
            +
                        @values = []
         
     | 
| 
      
 246 
     | 
    
         
            +
                      end
         
     | 
| 
      
 247 
     | 
    
         
            +
                      
         
     | 
| 
      
 248 
     | 
    
         
            +
                      def <<(value_)
         
     | 
| 
      
 249 
     | 
    
         
            +
                        @values << value_
         
     | 
| 
      
 250 
     | 
    
         
            +
                      end
         
     | 
| 
      
 251 
     | 
    
         
            +
                      
         
     | 
| 
      
 252 
     | 
    
         
            +
                      def assert_empty
         
     | 
| 
      
 253 
     | 
    
         
            +
                        if @values.size > 0
         
     | 
| 
      
 254 
     | 
    
         
            +
                          names_ = @values.map do |val_|
         
     | 
| 
      
 255 
     | 
    
         
            +
                            val_.kind_of?(Base) ? val_._wkt_typename : val_.inspect
         
     | 
| 
      
 256 
     | 
    
         
            +
                          end
         
     | 
| 
      
 257 
     | 
    
         
            +
                          raise Error::ParseError, "#{@remaining} unexpected arguments: #{names_.join(', ')}"
         
     | 
| 
      
 258 
     | 
    
         
            +
                        end
         
     | 
| 
      
 259 
     | 
    
         
            +
                      end
         
     | 
| 
      
 260 
     | 
    
         
            +
                      
         
     | 
| 
      
 261 
     | 
    
         
            +
                      def find_first(klass_)
         
     | 
| 
      
 262 
     | 
    
         
            +
                        @values.each_with_index do |val_, index_|
         
     | 
| 
      
 263 
     | 
    
         
            +
                          if val_.kind_of?(klass_)
         
     | 
| 
      
 264 
     | 
    
         
            +
                            @values.slice!(index_)
         
     | 
| 
      
 265 
     | 
    
         
            +
                            return val_
         
     | 
| 
      
 266 
     | 
    
         
            +
                          end
         
     | 
| 
      
 267 
     | 
    
         
            +
                        end
         
     | 
| 
      
 268 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 269 
     | 
    
         
            +
                      end
         
     | 
| 
      
 270 
     | 
    
         
            +
                      
         
     | 
| 
      
 271 
     | 
    
         
            +
                      def find_all(klass_)
         
     | 
| 
      
 272 
     | 
    
         
            +
                        results_ = []
         
     | 
| 
      
 273 
     | 
    
         
            +
                        nvalues_ = []
         
     | 
| 
      
 274 
     | 
    
         
            +
                        @values.each do |val_|
         
     | 
| 
      
 275 
     | 
    
         
            +
                          if val_.kind_of?(klass_)
         
     | 
| 
      
 276 
     | 
    
         
            +
                            results_ << val_
         
     | 
| 
      
 277 
     | 
    
         
            +
                          else
         
     | 
| 
      
 278 
     | 
    
         
            +
                            nvalues_ << val_
         
     | 
| 
      
 279 
     | 
    
         
            +
                          end
         
     | 
| 
      
 280 
     | 
    
         
            +
                        end
         
     | 
| 
      
 281 
     | 
    
         
            +
                        @values = nvalues_
         
     | 
| 
      
 282 
     | 
    
         
            +
                        results_
         
     | 
| 
      
 283 
     | 
    
         
            +
                      end
         
     | 
| 
      
 284 
     | 
    
         
            +
                      
         
     | 
| 
      
 285 
     | 
    
         
            +
                      def shift(klass_=nil)
         
     | 
| 
      
 286 
     | 
    
         
            +
                        val_ = @values.shift
         
     | 
| 
      
 287 
     | 
    
         
            +
                        unless val_
         
     | 
| 
      
 288 
     | 
    
         
            +
                          raise Error::ParseError, "No arguments left... expected #{klass_}"
         
     | 
| 
      
 289 
     | 
    
         
            +
                        end
         
     | 
| 
      
 290 
     | 
    
         
            +
                        if klass_ && !val_.kind_of?(klass_)
         
     | 
| 
      
 291 
     | 
    
         
            +
                          raise Error::ParseError, "Expected #{klass_} but got #{val_.class}"
         
     | 
| 
      
 292 
     | 
    
         
            +
                        end
         
     | 
| 
      
 293 
     | 
    
         
            +
                        val_
         
     | 
| 
      
 294 
     | 
    
         
            +
                      end
         
     | 
| 
      
 295 
     | 
    
         
            +
                      
         
     | 
| 
      
 296 
     | 
    
         
            +
                    end
         
     | 
| 
      
 297 
     | 
    
         
            +
                    
         
     | 
| 
      
 298 
     | 
    
         
            +
                    
         
     | 
| 
      
 299 
     | 
    
         
            +
                  end
         
     | 
| 
      
 300 
     | 
    
         
            +
                  
         
     | 
| 
      
 301 
     | 
    
         
            +
                  
         
     | 
| 
      
 302 
     | 
    
         
            +
                end
         
     | 
| 
      
 303 
     | 
    
         
            +
                
         
     | 
| 
      
 304 
     | 
    
         
            +
                
         
     | 
| 
      
 305 
     | 
    
         
            +
              end
         
     | 
| 
      
 306 
     | 
    
         
            +
              
         
     | 
| 
      
 307 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/rgeo/coord_sys/proj4.rb
    CHANGED
    
    | 
         @@ -168,6 +168,9 @@ module RGeo 
     | 
|
| 
       168 
168 
     | 
    
         
             
                        if defn_.kind_of?(::Hash)
         
     | 
| 
       169 
169 
     | 
    
         
             
                          defn_ = defn_.map{ |k_, v_| v_ ? "+#{k_}=#{v_}" : "+#{k_}" }.join(' ')
         
     | 
| 
       170 
170 
     | 
    
         
             
                        end
         
     | 
| 
      
 171 
     | 
    
         
            +
                        unless defn_ =~ /^\s*\+/
         
     | 
| 
      
 172 
     | 
    
         
            +
                          defn_ = defn_.sub(/^(\s*)/, '\1+').gsub(/(\s+)([^+\s])/, '\1+\2')
         
     | 
| 
      
 173 
     | 
    
         
            +
                        end
         
     | 
| 
       171 
174 
     | 
    
         
             
                        result_ = _create(defn_)
         
     | 
| 
       172 
175 
     | 
    
         
             
                        result_ = nil unless result_._valid?
         
     | 
| 
       173 
176 
     | 
    
         
             
                      end
         
     |