local-geocoder 0.1.1
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 +15 -0
- data/bin/local_geocode +42 -0
- data/ext/geometry/GeometryService.java +49 -0
- data/ext/geometry/Point.java +27 -0
- data/ext/geometry/Polygon.java +88 -0
- data/ext/geometry/RPoint.java +72 -0
- data/ext/geometry/RPolygon.java +111 -0
- data/ext/geometry/RRect.java +96 -0
- data/ext/geometry/Rect.java +49 -0
- data/ext/geometry/extconf.rb +5 -0
- data/lib/local_geocoder.rb +23 -0
- data/lib/local_geocoder/data_source.rb +57 -0
- data/lib/local_geocoder/geocoder.rb +48 -0
- data/lib/local_geocoder/geometry/point.rb +18 -0
- data/lib/local_geocoder/geometry/polygon.rb +69 -0
- data/lib/local_geocoder/geometry/rect.rb +22 -0
- data/lib/local_geocoder/version.rb +3 -0
- metadata +117 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            !binary "U0hBMQ==":
         | 
| 3 | 
            +
              metadata.gz: !binary |-
         | 
| 4 | 
            +
                MGIwNmFlYmZlNGVmNDExZDZkOTMxZGJmODU4NGNhNDIyMzY3MTZkNA==
         | 
| 5 | 
            +
              data.tar.gz: !binary |-
         | 
| 6 | 
            +
                ZDIxMWZmNmVmZGYwZTZmYmFkYWVhNDg3YjhhYTY4ZTNhOGQ5YmJjMQ==
         | 
| 7 | 
            +
            !binary "U0hBNTEy":
         | 
| 8 | 
            +
              metadata.gz: !binary |-
         | 
| 9 | 
            +
                ODc3YjAzMGNiNjQyZTU3NDgwOTAzOTI2ZWZjOGYzOTk1ODNjNWMyZDQ3MWIz
         | 
| 10 | 
            +
                ZThkMjQwMDRmMTRkN2ZlOTdhYTQ0Njg0YzY3NWQzMTUxM2I4YWQ1MmQ3ZDc1
         | 
| 11 | 
            +
                NTQ3ODE1N2MyMTFjYjIyYzMzOTEwZjkyZGM1N2JjYzM2NGFmZjY=
         | 
| 12 | 
            +
              data.tar.gz: !binary |-
         | 
| 13 | 
            +
                ZGRkNGQ3NjQ2OTE4MTUyYzU5Yjg3MzVhODg5Yjg4ZWI2MjNmY2UxZmE0YzQw
         | 
| 14 | 
            +
                ZDAyZmNiZWNmYTJiNmY1ZjU5ODQ5MjRjMTlmODQ2OTgwMjYyMWY3YmE3ZTVj
         | 
| 15 | 
            +
                YTg0NGExZjA1MDFiYzQ0ZGUyMjQ5MjIwN2FlODNlNWViZjA0OTU=
         | 
    
        data/bin/local_geocode
    ADDED
    
    | @@ -0,0 +1,42 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "../lib"))
         | 
| 4 | 
            +
            require "local_geocoder"
         | 
| 5 | 
            +
            require "trollop"
         | 
| 6 | 
            +
            require "csv"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            DEFAULT_TEMPLATE = '(?<lng>\-?\d+.?\d+)[,\t ]\s?(?<lat>\-?\d+.?\d+)'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            opts = Trollop::options do
         | 
| 11 | 
            +
              version "local_geocode #{LocalGeocoder::VERSION}"
         | 
| 12 | 
            +
              banner <<-EOS
         | 
| 13 | 
            +
            Local Geocoder
         | 
| 14 | 
            +
            ---------------
         | 
| 15 | 
            +
            Reverse geocodes lng,lat pairs into Country codes (and State + County within the USA). Each line of Stdin is read and has lng,lat pairs extracted (see --template below for how) and the resulting reverse geocode is output to Stdout.
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            Usage:
         | 
| 18 | 
            +
              local_geocode [options] file
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            Example:
         | 
| 21 | 
            +
            > echo "-122.4194155, 37.7749295" | local_geocode 
         | 
| 22 | 
            +
            > United States of America (USA), California (CA), San Francisco
         | 
| 23 | 
            +
             
         | 
| 24 | 
            +
            Options:
         | 
| 25 | 
            +
            EOS
         | 
| 26 | 
            +
              opt 'template', "The regex used to parse lng,lat paris from the input stream", :default => DEFAULT_TEMPLATE, :short => :t
         | 
| 27 | 
            +
            end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            require "local_geocoder"
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            lc = LocalGeocoder::Geocoder.new
         | 
| 32 | 
            +
            ARGF.each_line do |l|
         | 
| 33 | 
            +
              data = l.match(Regexp.new(opts["template"]))
         | 
| 34 | 
            +
              result = if data.nil?
         | 
| 35 | 
            +
                LocalGeocoder::Result.new
         | 
| 36 | 
            +
              else
         | 
| 37 | 
            +
                lng, lat = data[:lng].to_f, data[:lat].to_f 
         | 
| 38 | 
            +
                lc.reverse_geocode(lng, lat)
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
              puts result.inspect
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            end
         | 
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            package geometry;
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import org.jruby.Ruby;
         | 
| 4 | 
            +
            import org.jruby.RubyArray;
         | 
| 5 | 
            +
            import org.jruby.RubyClass;
         | 
| 6 | 
            +
            import org.jruby.RubyFixnum;
         | 
| 7 | 
            +
            import org.jruby.RubyModule;
         | 
| 8 | 
            +
            import org.jruby.RubyObject;
         | 
| 9 | 
            +
            import org.jruby.anno.JRubyClass;
         | 
| 10 | 
            +
            import org.jruby.anno.JRubyMethod;
         | 
| 11 | 
            +
            import org.jruby.runtime.ObjectAllocator;
         | 
| 12 | 
            +
            import org.jruby.runtime.ThreadContext;
         | 
| 13 | 
            +
            import org.jruby.runtime.builtin.IRubyObject;
         | 
| 14 | 
            +
            import org.jruby.runtime.load.BasicLibraryService;
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            public class GeometryService implements BasicLibraryService {
         | 
| 17 | 
            +
              private Ruby runtime;
         | 
| 18 | 
            +
              
         | 
| 19 | 
            +
              public boolean basicLoad(Ruby runtime) {
         | 
| 20 | 
            +
                this.runtime = runtime;
         | 
| 21 | 
            +
                RubyModule lc = runtime.defineModule("LocalGeocoder");
         | 
| 22 | 
            +
                RubyModule geo = lc.defineModuleUnder("Geometry");
         | 
| 23 | 
            +
                
         | 
| 24 | 
            +
                RubyClass point = geo.defineClassUnder("Point", runtime.getObject(), new ObjectAllocator() {
         | 
| 25 | 
            +
                  public IRubyObject allocate(Ruby runtime, RubyClass rubyClass) {
         | 
| 26 | 
            +
                    return new RPoint(runtime, rubyClass);
         | 
| 27 | 
            +
                  }
         | 
| 28 | 
            +
                });
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                RubyClass rect = geo.defineClassUnder("Rect", runtime.getObject(), new ObjectAllocator() {
         | 
| 31 | 
            +
                  public IRubyObject allocate(Ruby runtime, RubyClass rubyClass) {
         | 
| 32 | 
            +
                    return new RRect(runtime, rubyClass);
         | 
| 33 | 
            +
                  }
         | 
| 34 | 
            +
                });
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                RubyClass polygon = geo.defineClassUnder("Polygon", runtime.getObject(), new ObjectAllocator() {
         | 
| 37 | 
            +
                  public IRubyObject allocate(Ruby runtime, RubyClass rubyClass) {
         | 
| 38 | 
            +
                    return new RPolygon(runtime, rubyClass);
         | 
| 39 | 
            +
                  }
         | 
| 40 | 
            +
                });
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                point.defineAnnotatedMethods(RPoint.class);    
         | 
| 43 | 
            +
                rect.defineAnnotatedMethods(RRect.class);
         | 
| 44 | 
            +
                polygon.defineAnnotatedMethods(RPolygon.class);
         | 
| 45 | 
            +
                return true;
         | 
| 46 | 
            +
              }
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            }
         | 
| 49 | 
            +
             | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            package geometry;
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            public class Point {
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              double x;
         | 
| 6 | 
            +
              double y;
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              public Point(double x, double y) {
         | 
| 9 | 
            +
                this.x = x;
         | 
| 10 | 
            +
                this.y = y;
         | 
| 11 | 
            +
              }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              public double getX() {
         | 
| 14 | 
            +
                return this.x;
         | 
| 15 | 
            +
              }
         | 
| 16 | 
            +
              
         | 
| 17 | 
            +
              public double getY() {
         | 
| 18 | 
            +
                return this.y;
         | 
| 19 | 
            +
              }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              public String toString() {
         | 
| 22 | 
            +
                return String.format("[%s,%s]", x, y);
         | 
| 23 | 
            +
              }
         | 
| 24 | 
            +
              
         | 
| 25 | 
            +
            }
         | 
| 26 | 
            +
             | 
| 27 | 
            +
             | 
| @@ -0,0 +1,88 @@ | |
| 1 | 
            +
            package geometry;
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            public class Polygon {
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              Point[] points;
         | 
| 6 | 
            +
              Rect boundingBox;
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              public Polygon(Point[] points) {
         | 
| 9 | 
            +
                this.points = points;
         | 
| 10 | 
            +
              } 
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              public Point[] getPoints() {
         | 
| 13 | 
            +
                return this.points;
         | 
| 14 | 
            +
              }
         | 
| 15 | 
            +
             
         | 
| 16 | 
            +
              public int numberOfPoints() {
         | 
| 17 | 
            +
                return this.points.length;
         | 
| 18 | 
            +
              }
         | 
| 19 | 
            +
             
         | 
| 20 | 
            +
              public Rect boundingBox() {
         | 
| 21 | 
            +
                if (boundingBox == null) {
         | 
| 22 | 
            +
                  double minX, minY, maxX, maxY;
         | 
| 23 | 
            +
                  minX = minY = Double.POSITIVE_INFINITY; 
         | 
| 24 | 
            +
                  maxX = maxY = Double.NEGATIVE_INFINITY;
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  for (Point p: this.points) {
         | 
| 27 | 
            +
                    
         | 
| 28 | 
            +
                    double x = p.getX();
         | 
| 29 | 
            +
                    double y = p.getY();
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    if (x < minX) 
         | 
| 32 | 
            +
                      minX = x;
         | 
| 33 | 
            +
                    if (x > maxX)
         | 
| 34 | 
            +
                      maxX = x;
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    if (y < minY) 
         | 
| 37 | 
            +
                      minY = y;
         | 
| 38 | 
            +
                    if (y > maxY)
         | 
| 39 | 
            +
                      maxY = y;
         | 
| 40 | 
            +
                  }
         | 
| 41 | 
            +
                   
         | 
| 42 | 
            +
                  this.boundingBox = new Rect(minX, minY, maxX-minX, maxY-minY); 
         | 
| 43 | 
            +
                }
         | 
| 44 | 
            +
             
         | 
| 45 | 
            +
                return this.boundingBox;
         | 
| 46 | 
            +
              }
         | 
| 47 | 
            +
              
         | 
| 48 | 
            +
              public String toString() {
         | 
| 49 | 
            +
                StringBuilder sb = new StringBuilder();
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                for (Point p : points) {
         | 
| 52 | 
            +
                  sb.append( p.toString() + "," );
         | 
| 53 | 
            +
                }
         | 
| 54 | 
            +
                return sb.toString();   
         | 
| 55 | 
            +
              }
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              public boolean containsPoint(Point point) {
         | 
| 58 | 
            +
                if (!this.boundingBox().containsPoint(point))
         | 
| 59 | 
            +
                  return false;
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                boolean containsPoint = false;
         | 
| 62 | 
            +
                int i = -1;
         | 
| 63 | 
            +
                int j = this.points.length - 1;
         | 
| 64 | 
            +
                while (++i < this.points.length) {
         | 
| 65 | 
            +
                  Point p1 = this.points[i];
         | 
| 66 | 
            +
                  Point p2 = this.points[j];
         | 
| 67 | 
            +
                  if (this.withinYBounds(point, p1, p2)) {
         | 
| 68 | 
            +
                    if (this.intersectsLineSegment(point, p1, p2)) {
         | 
| 69 | 
            +
                      containsPoint = !containsPoint;
         | 
| 70 | 
            +
                    }
         | 
| 71 | 
            +
                  }
         | 
| 72 | 
            +
                  j = i;
         | 
| 73 | 
            +
                }
         | 
| 74 | 
            +
                return containsPoint; 
         | 
| 75 | 
            +
              }
         | 
| 76 | 
            +
              
         | 
| 77 | 
            +
              private boolean intersectsLineSegment(Point point, Point p1, Point p2) {
         | 
| 78 | 
            +
                return (point.getX() < (p2.getX() - p1.getX()) * (point.getY() - p1.getY()) / (p2.getY() - p1.getY()) + p1.getX());   
         | 
| 79 | 
            +
              }      
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              private boolean withinYBounds(Point point, Point p1, Point p2) {
         | 
| 82 | 
            +
                return (p1.getY() <= point.getY() && point.getY() < p2.getY()) ||
         | 
| 83 | 
            +
                  (p2.getY() <= point.getY() && point.getY() < p1.getY());
         | 
| 84 | 
            +
              }
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            }
         | 
| 87 | 
            +
             | 
| 88 | 
            +
             | 
| @@ -0,0 +1,72 @@ | |
| 1 | 
            +
            package geometry;
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import org.jruby.Ruby;
         | 
| 4 | 
            +
            import org.jruby.RubyArray;
         | 
| 5 | 
            +
            import org.jruby.RubyClass;
         | 
| 6 | 
            +
            import org.jruby.RubyFixnum;
         | 
| 7 | 
            +
            import org.jruby.RubyModule;
         | 
| 8 | 
            +
            import org.jruby.RubyObject;
         | 
| 9 | 
            +
            import org.jruby.anno.JRubyClass;
         | 
| 10 | 
            +
            import org.jruby.anno.JRubyMethod;
         | 
| 11 | 
            +
            import org.jruby.runtime.ObjectAllocator;
         | 
| 12 | 
            +
            import org.jruby.runtime.ThreadContext;
         | 
| 13 | 
            +
            import org.jruby.runtime.builtin.IRubyObject;
         | 
| 14 | 
            +
            import org.jruby.runtime.load.BasicLibraryService;
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            @JRubyClass(name = "LocalGeocoder::Geometry::Point")
         | 
| 17 | 
            +
            public class RPoint extends RubyObject {
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              Point point;
         | 
| 20 | 
            +
              IRubyObject data;
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              public RPoint(final Ruby runtime, RubyClass rubyClass) {
         | 
| 23 | 
            +
                super(runtime, rubyClass);
         | 
| 24 | 
            +
              }
         | 
| 25 | 
            +
              
         | 
| 26 | 
            +
              @JRubyMethod(name = "initialize", required = 2, optional = 1)
         | 
| 27 | 
            +
              public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
         | 
| 28 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 29 | 
            +
                double x = args[0].convertToFloat().getDoubleValue();
         | 
| 30 | 
            +
                double y = args[1].convertToFloat().getDoubleValue();
         | 
| 31 | 
            +
                
         | 
| 32 | 
            +
                this.point = new Point(x,y);
         | 
| 33 | 
            +
                this.data = context.nil;
         | 
| 34 | 
            +
                if (args.length > 2) {
         | 
| 35 | 
            +
                  this.data = args[2];
         | 
| 36 | 
            +
                }
         | 
| 37 | 
            +
                
         | 
| 38 | 
            +
                return context.nil;
         | 
| 39 | 
            +
              }
         | 
| 40 | 
            +
              
         | 
| 41 | 
            +
              public void setPoint(Point point) {
         | 
| 42 | 
            +
                this.point = point;
         | 
| 43 | 
            +
              }
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              public Point getJava() {
         | 
| 46 | 
            +
                return this.point;
         | 
| 47 | 
            +
              }
         | 
| 48 | 
            +
             
         | 
| 49 | 
            +
              @JRubyMethod(name = "x")
         | 
| 50 | 
            +
              public IRubyObject x(ThreadContext context) {
         | 
| 51 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 52 | 
            +
                return ruby.newFloat(point.getX());
         | 
| 53 | 
            +
              }
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              @JRubyMethod(name = "y")
         | 
| 56 | 
            +
              public IRubyObject y(ThreadContext context) {
         | 
| 57 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 58 | 
            +
                return ruby.newFloat(point.getY());
         | 
| 59 | 
            +
              }
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              @JRubyMethod(name = "data")
         | 
| 62 | 
            +
              public IRubyObject data(ThreadContext context) {
         | 
| 63 | 
            +
                return data;
         | 
| 64 | 
            +
              }
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              @JRubyMethod(name = "inspect")
         | 
| 67 | 
            +
              public IRubyObject inspect(ThreadContext context) {
         | 
| 68 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 69 | 
            +
                return ruby.newString(point.toString());
         | 
| 70 | 
            +
              }
         | 
| 71 | 
            +
              
         | 
| 72 | 
            +
            }
         | 
| @@ -0,0 +1,111 @@ | |
| 1 | 
            +
            package geometry;
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import org.jruby.Ruby;
         | 
| 4 | 
            +
            import org.jruby.RubyArray;
         | 
| 5 | 
            +
            import org.jruby.RubyClass;
         | 
| 6 | 
            +
            import org.jruby.RubyFixnum;
         | 
| 7 | 
            +
            import org.jruby.RubyModule;
         | 
| 8 | 
            +
            import org.jruby.RubyObject;
         | 
| 9 | 
            +
            import org.jruby.anno.JRubyClass;
         | 
| 10 | 
            +
            import org.jruby.anno.JRubyMethod;
         | 
| 11 | 
            +
            import org.jruby.runtime.ObjectAllocator;
         | 
| 12 | 
            +
            import org.jruby.runtime.ThreadContext;
         | 
| 13 | 
            +
            import org.jruby.runtime.builtin.IRubyObject;
         | 
| 14 | 
            +
            import org.jruby.runtime.load.BasicLibraryService;
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            @JRubyClass(name = "LocalGeocoder::Geometry::Polygon")  
         | 
| 17 | 
            +
            public class RPolygon extends RubyObject {
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              Polygon polygon;
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              public RPolygon(final Ruby runtime, RubyClass rubyClass) {
         | 
| 22 | 
            +
                super(runtime, rubyClass);
         | 
| 23 | 
            +
              }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              public void setPolygon(Polygon polygon) {
         | 
| 26 | 
            +
                this.polygon = polygon; 
         | 
| 27 | 
            +
              }
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              @JRubyMethod(name = "initialize")
         | 
| 30 | 
            +
              public IRubyObject initialize(ThreadContext context, IRubyObject rps) {
         | 
| 31 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                RubyArray rPoints = (RubyArray) rps;
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                Point[] points = new Point[rPoints.getLength()];
         | 
| 36 | 
            +
                for (int i = 0; i < rPoints.getLength(); i++) {
         | 
| 37 | 
            +
                  points[i] = ((RPoint) rPoints.get(i)).getJava();
         | 
| 38 | 
            +
                }
         | 
| 39 | 
            +
                
         | 
| 40 | 
            +
                this.polygon = new Polygon(points);
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                return context.nil;
         | 
| 43 | 
            +
              }
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              @JRubyMethod(meta = true, name = "from_point_array")
         | 
| 46 | 
            +
              public static IRubyObject fromPointArray(ThreadContext context, IRubyObject klazz, IRubyObject pts) {
         | 
| 47 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                RubyArray rpts = (RubyArray) pts;
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                Point[] points = new Point[rpts.getLength()];
         | 
| 52 | 
            +
                for (int i = 0; i < rpts.getLength(); i++) {
         | 
| 53 | 
            +
                  double x = ((Number) ((RubyArray) rpts.get(i)).get(0)).doubleValue();
         | 
| 54 | 
            +
                  double y = ((Number) ((RubyArray) rpts.get(i)).get(1)).doubleValue();
         | 
| 55 | 
            +
                  points[i] = new Point(x,y);
         | 
| 56 | 
            +
                }
         | 
| 57 | 
            +
               
         | 
| 58 | 
            +
                IRubyObject obj = ((RubyClass) klazz).allocate();
         | 
| 59 | 
            +
                ((RPolygon) obj).setPolygon(new Polygon(points));
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                return obj;
         | 
| 62 | 
            +
              }
         | 
| 63 | 
            +
             | 
| 64 | 
            +
              @JRubyMethod
         | 
| 65 | 
            +
              public IRubyObject number_of_points(ThreadContext context) {
         | 
| 66 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 67 | 
            +
                int i = this.polygon.numberOfPoints();
         | 
| 68 | 
            +
                return ruby.newFixnum(i);
         | 
| 69 | 
            +
              }
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              @JRubyMethod(name = "points")
         | 
| 72 | 
            +
              public IRubyObject points(ThreadContext context) {
         | 
| 73 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                Point[] points = this.polygon.getPoints();
         | 
| 76 | 
            +
                RPoint[] rPoints = new RPoint[points.length];
         | 
| 77 | 
            +
                for (int i = 0; i < points.length; i++) {
         | 
| 78 | 
            +
                  RPoint rPoint = new RPoint(ruby, (RubyClass)ruby.getClassFromPath("LocalGeocoder::Geometry::Point"));
         | 
| 79 | 
            +
                  rPoint.setPoint(points[i]);
         | 
| 80 | 
            +
                  rPoints[i] = rPoint;
         | 
| 81 | 
            +
                }
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                return ruby.newArray(rPoints);
         | 
| 84 | 
            +
              }
         | 
| 85 | 
            +
             | 
| 86 | 
            +
              @JRubyMethod(name = "bounding_box")
         | 
| 87 | 
            +
              public IRubyObject boundingBox(ThreadContext context) {
         | 
| 88 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 89 | 
            +
                
         | 
| 90 | 
            +
                Rect rect = this.polygon.boundingBox();
         | 
| 91 | 
            +
                RRect rRect = new RRect(ruby, (RubyClass)ruby.getClassFromPath("LocalGeocoder::Geometry::Rect"));
         | 
| 92 | 
            +
                rRect.setRect(rect);
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                return rRect;
         | 
| 95 | 
            +
              }
         | 
| 96 | 
            +
             | 
| 97 | 
            +
              @JRubyMethod(name = "contains_point?")
         | 
| 98 | 
            +
              public IRubyObject containsPoint(ThreadContext context, IRubyObject rPoint) {
         | 
| 99 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 100 | 
            +
                
         | 
| 101 | 
            +
                boolean result = this.polygon.containsPoint(((RPoint)rPoint).getJava());
         | 
| 102 | 
            +
                return ruby.newBoolean(result);
         | 
| 103 | 
            +
              }
         | 
| 104 | 
            +
             | 
| 105 | 
            +
              @JRubyMethod(name = "inspect")
         | 
| 106 | 
            +
              public IRubyObject inspect(ThreadContext context) {
         | 
| 107 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 108 | 
            +
                return ruby.newString(polygon.toString());
         | 
| 109 | 
            +
              }
         | 
| 110 | 
            +
              
         | 
| 111 | 
            +
            }
         | 
| @@ -0,0 +1,96 @@ | |
| 1 | 
            +
            package geometry;
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import org.jruby.Ruby;
         | 
| 4 | 
            +
            import org.jruby.RubyArray;
         | 
| 5 | 
            +
            import org.jruby.RubyClass;
         | 
| 6 | 
            +
            import org.jruby.RubyFixnum;
         | 
| 7 | 
            +
            import org.jruby.RubyModule;
         | 
| 8 | 
            +
            import org.jruby.RubyObject;
         | 
| 9 | 
            +
            import org.jruby.anno.JRubyClass;
         | 
| 10 | 
            +
            import org.jruby.anno.JRubyMethod;
         | 
| 11 | 
            +
            import org.jruby.runtime.ObjectAllocator;
         | 
| 12 | 
            +
            import org.jruby.runtime.ThreadContext;
         | 
| 13 | 
            +
            import org.jruby.runtime.builtin.IRubyObject;
         | 
| 14 | 
            +
            import org.jruby.runtime.load.BasicLibraryService;
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            @JRubyClass(name = "LocalGeocoder::Geometry::Rect")  
         | 
| 17 | 
            +
            public class RRect extends RubyObject {
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              Rect rect;
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              public RRect(final Ruby runtime, RubyClass rubyClass) {
         | 
| 22 | 
            +
                super(runtime, rubyClass);
         | 
| 23 | 
            +
              }
         | 
| 24 | 
            +
             
         | 
| 25 | 
            +
              @JRubyMethod(name = "initialize", required = 4)
         | 
| 26 | 
            +
              public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
         | 
| 27 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                double dX = args[0].convertToFloat().getDoubleValue();
         | 
| 30 | 
            +
                double dY = args[1].convertToFloat().getDoubleValue();
         | 
| 31 | 
            +
                double dWidth = args[2].convertToFloat().getDoubleValue();
         | 
| 32 | 
            +
                double dHeight = args[3].convertToFloat().getDoubleValue();
         | 
| 33 | 
            +
                
         | 
| 34 | 
            +
                this.rect = new Rect(dX,dY,dWidth,dHeight);
         | 
| 35 | 
            +
                  
         | 
| 36 | 
            +
                return context.nil;
         | 
| 37 | 
            +
              }
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              public void setRect(Rect rect) {
         | 
| 40 | 
            +
                this.rect = rect;
         | 
| 41 | 
            +
              }
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              public Rect getJava() {
         | 
| 44 | 
            +
                return this.rect;
         | 
| 45 | 
            +
              }
         | 
| 46 | 
            +
              
         | 
| 47 | 
            +
              @JRubyMethod(name = "x")
         | 
| 48 | 
            +
              public IRubyObject x(ThreadContext context) {
         | 
| 49 | 
            +
                Ruby ruby = context.getRuntime(); 
         | 
| 50 | 
            +
                return ruby.newFloat(rect.getX());
         | 
| 51 | 
            +
              }
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              @JRubyMethod(name = "y")
         | 
| 54 | 
            +
              public IRubyObject y(ThreadContext context) {
         | 
| 55 | 
            +
                Ruby ruby = context.getRuntime(); 
         | 
| 56 | 
            +
                return ruby.newFloat(rect.getY());
         | 
| 57 | 
            +
              }
         | 
| 58 | 
            +
              
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              @JRubyMethod(name = "width")
         | 
| 61 | 
            +
              public IRubyObject widht(ThreadContext context) {
         | 
| 62 | 
            +
                Ruby ruby = context.getRuntime(); 
         | 
| 63 | 
            +
                return ruby.newFloat(rect.getWidth());
         | 
| 64 | 
            +
              }
         | 
| 65 | 
            +
              
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              @JRubyMethod(name = "height")
         | 
| 68 | 
            +
              public IRubyObject height(ThreadContext context) {
         | 
| 69 | 
            +
                Ruby ruby = context.getRuntime(); 
         | 
| 70 | 
            +
                return ruby.newFloat(rect.getHeight());
         | 
| 71 | 
            +
              }
         | 
| 72 | 
            +
             | 
| 73 | 
            +
              @JRubyMethod(name = "==")
         | 
| 74 | 
            +
              public IRubyObject r_eql(ThreadContext context, IRubyObject rRect) {
         | 
| 75 | 
            +
                Ruby ruby = context.getRuntime(); 
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                
         | 
| 78 | 
            +
                return ruby.newBoolean(rect.equals(((RRect) rRect).getJava()));
         | 
| 79 | 
            +
              } 
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              @JRubyMethod(name = "contains_point?")
         | 
| 82 | 
            +
              public IRubyObject containsPoint(ThreadContext context, IRubyObject point) {
         | 
| 83 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 84 | 
            +
                boolean result = this.rect.containsPoint(((RPoint)point).getJava());
         | 
| 85 | 
            +
                  
         | 
| 86 | 
            +
                return ruby.newBoolean(result);
         | 
| 87 | 
            +
              }
         | 
| 88 | 
            +
             | 
| 89 | 
            +
              @JRubyMethod(name = "inspect")
         | 
| 90 | 
            +
              public IRubyObject inspect(ThreadContext context) {
         | 
| 91 | 
            +
                Ruby ruby = context.getRuntime();
         | 
| 92 | 
            +
                String str = String.format("[%s,%s],[%s,%s]", rect.getX(),rect.getY(),rect.getX()+rect.getWidth(),rect.getY()+rect.getHeight()); 
         | 
| 93 | 
            +
                return ruby.newString(str);
         | 
| 94 | 
            +
              }
         | 
| 95 | 
            +
              
         | 
| 96 | 
            +
            }
         | 
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            package geometry;
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            public class Rect {
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              double x;
         | 
| 6 | 
            +
              double y;
         | 
| 7 | 
            +
              double width;
         | 
| 8 | 
            +
              double height;
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              public Rect(double x, double y, double width, double height) {
         | 
| 11 | 
            +
                this.x = x;
         | 
| 12 | 
            +
                this.y = y;
         | 
| 13 | 
            +
                this.width = width;
         | 
| 14 | 
            +
                this.height = height;
         | 
| 15 | 
            +
              } 
         | 
| 16 | 
            +
              
         | 
| 17 | 
            +
              public boolean containsPoint(Point point) {
         | 
| 18 | 
            +
                return point.getX() >= this.x && point.getY() >= this.y &&
         | 
| 19 | 
            +
                       point.getX() <= (this.x + this.width) && point.getY() <= (this.y + this.height);
         | 
| 20 | 
            +
              }
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              public double getX() {
         | 
| 23 | 
            +
                return this.x;
         | 
| 24 | 
            +
              }
         | 
| 25 | 
            +
                
         | 
| 26 | 
            +
              public double getY() {
         | 
| 27 | 
            +
                return this.y;
         | 
| 28 | 
            +
              }
         | 
| 29 | 
            +
              
         | 
| 30 | 
            +
              public double getWidth() {
         | 
| 31 | 
            +
                return this.width;
         | 
| 32 | 
            +
              }
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              public double getHeight() {
         | 
| 35 | 
            +
                return this.height;
         | 
| 36 | 
            +
              }
         | 
| 37 | 
            +
              
         | 
| 38 | 
            +
              @Override public boolean equals(Object other) {
         | 
| 39 | 
            +
                boolean result = false;
         | 
| 40 | 
            +
                if (other instanceof Rect) {
         | 
| 41 | 
            +
                  Rect rect = (Rect) other;
         | 
| 42 | 
            +
                  result = (this.x == rect.getX() && this.y == rect.getY() && 
         | 
| 43 | 
            +
                    this.width == rect.getWidth() && this.height == rect.getHeight());
         | 
| 44 | 
            +
                }
         | 
| 45 | 
            +
                return result;
         | 
| 46 | 
            +
              }
         | 
| 47 | 
            +
              
         | 
| 48 | 
            +
            }
         | 
| 49 | 
            +
             | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            require "json"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module LocalGeocoder
         | 
| 4 | 
            +
              DATA_DIR = "data"
         | 
| 5 | 
            +
            end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            require "local_geocoder/version"
         | 
| 8 | 
            +
            require "local_geocoder/data_source"
         | 
| 9 | 
            +
            require "local_geocoder/geocoder"
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            if RUBY_PLATFORM =~ /java/
         | 
| 12 | 
            +
              require 'jruby'
         | 
| 13 | 
            +
              require 'geometry.jar' 
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              java_import 'geometry.GeometryService' 
         | 
| 16 | 
            +
              
         | 
| 17 | 
            +
              Java::Geometry::GeometryService.new.basicLoad(JRuby.runtime)
         | 
| 18 | 
            +
            else
         | 
| 19 | 
            +
              require "local_geocoder/geometry/point"
         | 
| 20 | 
            +
              require "local_geocoder/geometry/rect"
         | 
| 21 | 
            +
              require "local_geocoder/geometry/polygon"
         | 
| 22 | 
            +
            end
         | 
| 23 | 
            +
             | 
| @@ -0,0 +1,57 @@ | |
| 1 | 
            +
            module LocalGeocoder
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              Entity = Struct.new(:short_name, :long_name, :geometries) do
         | 
| 4 | 
            +
                def inspect
         | 
| 5 | 
            +
                  "#{self.long_name}#{self.short_name.empty? ? "" : ' ('+self.short_name+')' }"
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              class DataSource
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def initialize(dir)
         | 
| 12 | 
            +
                  @countries = load_data(dir, "countries/features.geo.json")
         | 
| 13 | 
            +
                  @administrative_areas_level_1 = Hash.new do |h,k|
         | 
| 14 | 
            +
                    h[k] = load_data(File.join(dir, "countries", k), "features.geo.json")
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                  @administrative_areas_level_2 = Hash.new do |h,k|
         | 
| 17 | 
            +
                    h[k] = load_data(File.join(dir, "countries", *k), "features.geo.json")
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def countries
         | 
| 22 | 
            +
                  @countries
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
                
         | 
| 25 | 
            +
                def administrative_areas_level_1(country_id)
         | 
| 26 | 
            +
                  return nil if country_id.nil?      
         | 
| 27 | 
            +
                  @administrative_areas_level_1[country_id]
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                def administrative_areas_level_2(country_id, aa1_id)
         | 
| 31 | 
            +
                  return nil if country_id.nil? || aa1_id.nil?
         | 
| 32 | 
            +
                  @administrative_areas_level_2[[country_id, aa1_id]]
         | 
| 33 | 
            +
                end 
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                private
         | 
| 36 | 
            +
             
         | 
| 37 | 
            +
                def load_data(dir, file)
         | 
| 38 | 
            +
                  features = JSON.load(File.open(File.join(dir, file)))['features']
         | 
| 39 | 
            +
                  features.map do |f|
         | 
| 40 | 
            +
                    id = f['id'] ? f['id'][/\w+$/] : ""
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    # Note: Perimeter is always first element in GeoJSON.
         | 
| 43 | 
            +
                    geometries = case f['geometry']['type']
         | 
| 44 | 
            +
                    when "MultiPolygon"
         | 
| 45 | 
            +
                      f['geometry']['coordinates'].map { |g| Geometry::Polygon.from_point_array(g.first) }
         | 
| 46 | 
            +
                    when "Polygon"
         | 
| 47 | 
            +
                      Array(Geometry::Polygon.from_point_array(f['geometry']['coordinates'].first))
         | 
| 48 | 
            +
                    else
         | 
| 49 | 
            +
                      raise "Don't know how to handle geometry type: #{f['geometry']['type']}"
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
                    Entity.new(id, f['properties']['name'], geometries)
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
                
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            module LocalGeocoder
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              Result = Struct.new(:country, :administrative_area_level_1, :administrative_area_level_2) do
         | 
| 4 | 
            +
                alias_method :state, :administrative_area_level_1
         | 
| 5 | 
            +
                alias_method :county, :administrative_area_level_2
         | 
| 6 | 
            +
                def inspect
         | 
| 7 | 
            +
                  "#{self.country.inspect}, #{self.administrative_area_level_1.inspect}, #{self.administrative_area_level_2.inspect}"
         | 
| 8 | 
            +
                end    
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
              
         | 
| 11 | 
            +
              class Geocoder
         | 
| 12 | 
            +
                
         | 
| 13 | 
            +
                def initialize
         | 
| 14 | 
            +
                  @data_source = DataSource.new(DATA_DIR) 
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def reverse_geocode(lng, lat)
         | 
| 18 | 
            +
                  country = find_result(lng, lat)
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
               
         | 
| 21 | 
            +
                private
         | 
| 22 | 
            +
                
         | 
| 23 | 
            +
                def find_result(lng, lat)
         | 
| 24 | 
            +
                  cnt = find_country(lng, lat)
         | 
| 25 | 
            +
                  aa1, aa2 = find_administrative_areas(cnt.short_name, lng, lat) if cnt && cnt.short_name == "USA"
         | 
| 26 | 
            +
                  Result.new(cnt, aa1, aa2) 
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
                
         | 
| 29 | 
            +
                def find_country(lng, lat)
         | 
| 30 | 
            +
                  @data_source.countries.find { |c|  contains_location?(c, lng, lat); }
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def find_administrative_areas(country_id, lng, lat)
         | 
| 34 | 
            +
                  aa1 = @data_source.administrative_areas_level_1(country_id).find { |a| contains_location?(a, lng, lat) }
         | 
| 35 | 
            +
                  return nil,nil if aa1.nil?
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  aa2 = @data_source.administrative_areas_level_2(country_id, aa1.short_name).find { |a| contains_location?(a, lng, lat) }
         | 
| 38 | 
            +
                  return aa1, aa2
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                def contains_location?(entity, lng, lat)
         | 
| 42 | 
            +
                  entity.geometries.any? { |g| g.contains_point?(Geometry::Point.new(lng, lat)) }
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            end
         | 
| 48 | 
            +
             | 
| @@ -0,0 +1,69 @@ | |
| 1 | 
            +
            module LocalGeocoder  
         | 
| 2 | 
            +
              module Geometry
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                class Polygon
         | 
| 5 | 
            +
                  attr_accessor :points
         | 
| 6 | 
            +
                  
         | 
| 7 | 
            +
                  def initialize(points)
         | 
| 8 | 
            +
                    @points = points
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                  
         | 
| 11 | 
            +
                  def self.from_point_array(points)
         | 
| 12 | 
            +
                    Polygon.new(points.map { |p| Point.new(*p) })
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                  
         | 
| 15 | 
            +
                  def number_of_points
         | 
| 16 | 
            +
                    @points.size
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  def [](i)
         | 
| 20 | 
            +
                    @points[i]
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                  
         | 
| 23 | 
            +
                  def bounding_box
         | 
| 24 | 
            +
                    @bounding_box ||= begin
         | 
| 25 | 
            +
                      min_x, max_x = @points.minmax_by { |p| p.x }.map { |p| p.x }
         | 
| 26 | 
            +
                      min_y, max_y = @points.minmax_by { |p| p.y }.map { |p| p.y }
         | 
| 27 | 
            +
                      Rect.new(min_x, min_y, max_x-min_x, max_y-min_y)
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  def contains_point?(point)
         | 
| 32 | 
            +
                    return false if !self.bounding_box.contains_point?(point)
         | 
| 33 | 
            +
                    
         | 
| 34 | 
            +
                    contains_point = false
         | 
| 35 | 
            +
                    i = -1
         | 
| 36 | 
            +
                    j = self.number_of_points - 1
         | 
| 37 | 
            +
                    while (i += 1) < self.number_of_points
         | 
| 38 | 
            +
                      p1 = self[i]; p2 = self[j]
         | 
| 39 | 
            +
                      if within_y_bounds?(point, p1, p2)
         | 
| 40 | 
            +
                        if intersects_line_segment?(point, p1, p2)
         | 
| 41 | 
            +
                          contains_point = !contains_point
         | 
| 42 | 
            +
                        end
         | 
| 43 | 
            +
                      end
         | 
| 44 | 
            +
                      j = i
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
                    return contains_point
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  def inspect
         | 
| 50 | 
            +
                    @points.map { |p| p.inspect }.join(",")
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  private
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  def within_y_bounds?(point, p1, p2)
         | 
| 56 | 
            +
                    (p1.y <= point.y && point.y < p2.y) || 
         | 
| 57 | 
            +
                      (p2.y <= point.y && point.y < p1.y)
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  def intersects_line_segment?(point, p1, p2)
         | 
| 61 | 
            +
                    (point.x < (p2.x - p1.x) * (point.y - p1.y) / 
         | 
| 62 | 
            +
                              (p2.y - p1.y) + p1.x)
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
                  
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
            end
         | 
| 69 | 
            +
             | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            module LocalGeocoder
         | 
| 2 | 
            +
              module Geometry
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                Rect = Struct.new(:x, :y, :width, :height) do
         | 
| 5 | 
            +
                  def contains_point?(point)
         | 
| 6 | 
            +
                    point.x >= self.x && point.y >= self.y &&
         | 
| 7 | 
            +
                      point.x <= (self.x+self.width) && point.y <= (self.y+self.height)
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
                
         | 
| 10 | 
            +
                  def ==(rect)
         | 
| 11 | 
            +
                    self.x == rect.x && self.y == rect.y &&
         | 
| 12 | 
            +
                      self.width == rect.width && self.height == rect.height
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                
         | 
| 15 | 
            +
                  def inspect
         | 
| 16 | 
            +
                    "[#{x},#{y}],[#{x+width},#{y+height}]"
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                  
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,117 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: local-geocoder
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.1.1
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - Aish Fenton
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: bin
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2013-05-09 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: trollop
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - ! '>='
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '0'
         | 
| 20 | 
            +
              type: :runtime
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - ! '>='
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '0'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: rake
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - ! '>='
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '0'
         | 
| 34 | 
            +
              type: :development
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - ! '>='
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '0'
         | 
| 41 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            +
              name: rspec
         | 
| 43 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            +
                requirements:
         | 
| 45 | 
            +
                - - ! '>='
         | 
| 46 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            +
                    version: '0'
         | 
| 48 | 
            +
              type: :development
         | 
| 49 | 
            +
              prerelease: false
         | 
| 50 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - ! '>='
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: '0'
         | 
| 55 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 56 | 
            +
              name: rake-compiler
         | 
| 57 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 | 
            +
                requirements:
         | 
| 59 | 
            +
                - - ! '>='
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: '0'
         | 
| 62 | 
            +
              type: :development
         | 
| 63 | 
            +
              prerelease: false
         | 
| 64 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 | 
            +
                requirements:
         | 
| 66 | 
            +
                - - ! '>='
         | 
| 67 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 68 | 
            +
                    version: '0'
         | 
| 69 | 
            +
            description: 
         | 
| 70 | 
            +
            email: 
         | 
| 71 | 
            +
            executables:
         | 
| 72 | 
            +
            - local_geocode
         | 
| 73 | 
            +
            extensions: []
         | 
| 74 | 
            +
            extra_rdoc_files: []
         | 
| 75 | 
            +
            files:
         | 
| 76 | 
            +
            - ext/geometry/GeometryService.java
         | 
| 77 | 
            +
            - ext/geometry/Point.java
         | 
| 78 | 
            +
            - ext/geometry/Polygon.java
         | 
| 79 | 
            +
            - ext/geometry/Rect.java
         | 
| 80 | 
            +
            - ext/geometry/RPoint.java
         | 
| 81 | 
            +
            - ext/geometry/RPolygon.java
         | 
| 82 | 
            +
            - ext/geometry/RRect.java
         | 
| 83 | 
            +
            - ext/geometry/extconf.rb
         | 
| 84 | 
            +
            - lib/local_geocoder/data_source.rb
         | 
| 85 | 
            +
            - lib/local_geocoder/geocoder.rb
         | 
| 86 | 
            +
            - lib/local_geocoder/geometry/point.rb
         | 
| 87 | 
            +
            - lib/local_geocoder/geometry/polygon.rb
         | 
| 88 | 
            +
            - lib/local_geocoder/geometry/rect.rb
         | 
| 89 | 
            +
            - lib/local_geocoder/version.rb
         | 
| 90 | 
            +
            - lib/local_geocoder.rb
         | 
| 91 | 
            +
            - bin/local_geocode
         | 
| 92 | 
            +
            homepage: 
         | 
| 93 | 
            +
            licenses: []
         | 
| 94 | 
            +
            metadata: {}
         | 
| 95 | 
            +
            post_install_message: 
         | 
| 96 | 
            +
            rdoc_options: []
         | 
| 97 | 
            +
            require_paths:
         | 
| 98 | 
            +
            - lib
         | 
| 99 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 100 | 
            +
              requirements:
         | 
| 101 | 
            +
              - - ! '>='
         | 
| 102 | 
            +
                - !ruby/object:Gem::Version
         | 
| 103 | 
            +
                  version: '0'
         | 
| 104 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 105 | 
            +
              requirements:
         | 
| 106 | 
            +
              - - ! '>='
         | 
| 107 | 
            +
                - !ruby/object:Gem::Version
         | 
| 108 | 
            +
                  version: '0'
         | 
| 109 | 
            +
            requirements: []
         | 
| 110 | 
            +
            rubyforge_project: 
         | 
| 111 | 
            +
            rubygems_version: 2.0.3
         | 
| 112 | 
            +
            signing_key: 
         | 
| 113 | 
            +
            specification_version: 4
         | 
| 114 | 
            +
            summary: Reverse geocodes lng, lat pairs into country codes (plus State and Counties
         | 
| 115 | 
            +
              within the US). Runs locally, with no external dependancies, and is fast enough
         | 
| 116 | 
            +
              for large batch jobs
         | 
| 117 | 
            +
            test_files: []
         |