lib/mapkit.rb in mapkit-0.0.3 vs lib/mapkit.rb in mapkit-1.0.0

- old
+ new

@@ -1,90 +1,86 @@ # Module to create tile for the google maps tile overlay module MapKit # consant for radiants RADIANT = Math::PI / 180.0 - + # the size of tiles in google maps TILE_SIZE = 256 - + # the constant earth radius in meters EARTH_RADIUS = 6_378_137 - + # the min latitude based on the mercator projection MIN_LATITUDE = -85.05112877 - + # the max latitude based on the mercator projection MAX_LATITUDE = 85.05112877 - + # the min longitude based on the mercator projection MIN_LONGITUDE = -180 - + # the max longitude based on the mercator projection MAX_LONGITUDE = 180 - + # the resolution in meters per pixel RESOLUTION = 2 * Math::PI * EARTH_RADIUS / TILE_SIZE - + # version of MapKit - VERSION = "0.0.3" - + VERSION = "1.0.0" + # The class represents an lat/lng point class Point attr_accessor :lat, :lng - + # initializes a point object using latitude and longitude def initialize(lat, lng) @lat, @lng = lat, lng end - + # returns true if point is in bounding_box, false otherwise def in?(bounding_box) top, left, bottom, right = bounding_box.coords (left..right) === @lng && (top..bottom) === @lat end - + # returns relative x and y for point in bounding_box def pixel(bounding_box) - top, left, bottom, right = bounding_box.coords - ws = bounding_box.width / TILE_SIZE - hs = bounding_box.height / TILE_SIZE - shift_lng = (@lng > 0) ? (@lng - left) : (left - @lng) - shift_lat = (@lat > 0) ? (top - @lat) : (@lat - top) - - [(shift_lng.abs / ws).to_i, (shift_lat.abs / hs).to_i] + x, y = MapKit.latlng2pixel(@lat, @lng, bounding_box.zoom) + tile_x, tile_y = MapKit.latlng2pixel(bounding_box.top, bounding_box.left, bounding_box.zoom) + [x-tile_x, y-tile_y] end end - - # The class represents a bounding box specified by a top/left point and a + + # The class represents a bounding box specified by a top/left point and a # bottom/right point (the coordinates can be pixels or degrees) class BoundingBox attr_accessor :top, :left, :bottom, :right, :zoom - - # initialize the bounding box using the positions of two points and a + + # initialize the bounding box using the positions of two points and a # optional zoom level # # top # left o------+ # | | # | | # +------o right # bottom # - def initialize(top, left, bottom, right, zoom = nil) + def initialize(top, left, bottom, right, zoom = 0) @top, @left, @bottom, @right, @zoom = top, left, bottom, right, zoom end - + # returns array of [top, left, bottom, right] def coords [@top, @left, @bottom, @right] end - + # returns the width of the bounding box in degrees def width @right - @left end - + # returns the height of the bounding box in degrees def height @top - @bottom end @@ -95,47 +91,47 @@ # returns [lat, lnt] of bounding box def center [@left + width / 2, @bottom + height / 2] end - + # grow bounding box by percentage def grow!(percent) lng = ((100.0 + percent) * (width / 2.0 / 100.0)) / 2.0 lat = ((100.0 + percent) * (height / 2.0 / 100.0)) / 2.0 @top += lat @left -= lng @bottom -= lat @right += lng end - + # grow bounding box by percentage and return new bounding box object def grow(percent) copy = self.clone copy.grow!(percent) copy end end - + # return bounding box for passed tile coordinates tiles def self.bounding_box(tile_x, tile_y, zoom) top, left, bottom, right = tile_bounds(tile_x, tile_y, zoom) BoundingBox.new(top, left, bottom, right, zoom) end - # returns bounds [top, left, bottom, right] of the given tile + # returns bounds [top, left, bottom, right] of the given tile # in WGS-94 coordinates def self.tile_bounds(tile_x, tile_y, zoom) pixel_x, pixel_y = tile2pixel(tile_x, tile_y) top, left = pixel2latlng(pixel_x, pixel_y, zoom) - + pixel_x, pixel_y = tile2pixel(tile_x + 1, tile_y + 1) bottom, right = pixel2latlng(pixel_x, pixel_y, zoom) - + [top, left, bottom, right] end - + # returns [lat, lng] shifted using the passed pixels and zoom def self.shift_latlng(lat, lng, shift_x, shift_y, zoom) pixel_x, pixel_y = latlng2pixel(lat.to_f, lng.to_f, zoom) pixel_x, pixel_y = pixel_x + shift_x, pixel_y + shift_y pixel2latlng(pixel_x, pixel_y, zoom) @@ -144,53 +140,53 @@ # returns pixel coordinates [x, y] based on the passed lat/lng WGS-84 # coordinates using the specified zoom level def self.latlng2pixel(lat, lng, zoom) lat = clip(lat.to_f, MIN_LATITUDE, MAX_LATITUDE) lng = clip(lng.to_f, MIN_LONGITUDE, MAX_LONGITUDE) - + x = (lng + 180.0) / 360.0 sin_lat = Math.sin(lat * RADIANT) y = 0.5 - Math.log((1.0 + sin_lat) / (1.0 - sin_lat)) / (4.0 * Math::PI) sx, sy = map_size(zoom) - + pixel_x = clip(x * sx + 0.5, 0.0, sx - 1.0) pixel_y = clip(y * sy + 0.5, 0.0, sy - 1.0) [pixel_x.to_i, pixel_y.to_i] end - + # returns lat/lng WGS-84 coordinates [lat, lng] basedon the passed pixel # coordinates using the specified zoom level def self.pixel2latlng(pixel_x, pixel_y, zoom) sx, sy = map_size(zoom) x = clip(pixel_x.to_f, 0.0, sx - 1.0) / sx - 0.5 y = 0.5 - clip(pixel_y.to_f, 0.0, sy - 1.0) / sy - + lat = 90.0 - 360.0 * Math.atan(Math.exp(-y * 2.0 * Math::PI)) / Math::PI lng = 360.0 * x [lat, lng] end - # returns the passed value in case it is in the passed range or the - # bounding min or max value + # returns the passed value in case it is in the passed range or the + # bounding min or max value def self.clip(val, min, max) (val < min) ? min : (val > max) ? max : val end # returns coordinates of tiles using passed pixel coordinates def self.pixel2tile(pixel_x, pixel_y) [pixel_x / TILE_SIZE, pixel_y / TILE_SIZE] end - + # returns coordinates of pixels using passed tile coordinates def self.tile2pixel(tile_x, tile_y) [tile_x * TILE_SIZE, tile_y * TILE_SIZE] end - + # returns the size [x, y] of the map using the passed zoom level def self.map_size(zoom) [TILE_SIZE << zoom, TILE_SIZE << zoom] end - + # returns resolution in meters per pixel for passed zoom level def self.resolution(zoom) RESOLUTION / (2 ** zoom) end end