3 # This piece of magic reads a GPX with SAX and spits out
6 # This would print every latitude value:
8 # gpx = OSM:GPXImporter.new('somefile.gpx')
9 # gpx.points {|p| puts p['latitude']}
12 require 'rexml/parsers/sax2parser'
19 def initialize(lat, lon, degrees_per_pixel, width, height)
20 #init me with your centre lat/lon, the number of degrees per pixel and the size of your image
23 @degrees_per_pixel = degrees_per_pixel
26 @dlon = width / 2 * degrees_per_pixel
27 @dlat = height / 2 * degrees_per_pixel * cos(@clat * PI / 180)
29 @tx = xsheet(@clon - @dlon)
30 @ty = ysheet(@clat - @dlat)
32 @bx = xsheet(@clon + @dlon)
33 @by = ysheet(@clat + @dlat)
37 #the following two functions will give you the x/y on the entire sheet
40 return 40008.0 / 360.0 * @degrees_per_pixel
44 log(tan(PI / 4 + (lat * PI / 180 / 2)))
51 #and these two will give you the right points on your image. all the constants can be reduced to speed things up. FIXME
54 return @height - ((ysheet(lat) - @ty) / (@by - @ty) * @height)
58 return ((xsheet(lon) - @tx) / (@bx - @tx) * @width)
64 attr_reader :possible_points
65 attr_reader :actual_points
66 attr_reader :tracksegs
68 def initialize(filename)
76 file = File.new(@filename)
77 parser = REXML::Parsers::SAX2Parser.new( file )
87 parser.listen( :start_element, %w{ trkpt }) do |uri,localname,qname,attributes|
88 lat = attributes['lat'].to_f
89 lon = attributes['lon'].to_f
94 parser.listen( :characters, %w{ ele } ) do |text|
99 parser.listen( :characters, %w{ time } ) do |text|
100 if text && text != ''
101 date = Time.parse(text)
106 parser.listen( :end_element, %w{ trkseg } ) do |uri, localname, qname|
110 parser.listen( :end_element, %w{ trkpt } ) do |uri,localname,qname|
111 if gotlatlon && gotdate
112 ele = '0' unless gotele
113 if lat < 90 && lat > -90 && lon > -180 && lon < 180
115 yield Hash['latitude' => lat,'longitude' => lon,'timestamp' => date,'altitude' => ele,'segment' => @tracksegs]
125 def get_picture(min_lat, min_lon, max_lat, max_lon, num_points)
129 rat= Math.cos( ((max_lat + min_lat)/2.0) / 180.0 * 3.141592)
130 proj = OSM::Mercator.new((min_lat + max_lat) / 2, (max_lon + min_lon) / 2, (max_lat - min_lat) / width / rat, width, height)
135 gc = Magick::Draw.new
136 gc.stroke_linejoin('miter')
139 gc.rectangle(0,0,width,height)
152 px = proj.x(p['longitude'])
153 py = proj.y(p['latitude'])
155 images[n].stroke_width(1)
156 images[n].stroke('#BBBBBB')
157 images[n].fill('#BBBBBB')
158 images[n].line(px, py, oldpx, oldpy ) unless first
160 images[mm].stroke_width(3)
161 images[mm].stroke('#000000')
162 images[mm].fill('#000000')
163 images[mm].line(px, py, oldpx, oldpy ) unless first
166 if m > num_points.to_f / frames.to_f * (mm+1)
174 il = Magick::ImageList.new
177 canvas = Magick::Image.new(width, height) {
178 self.background_color = 'white'
181 images[n].draw(canvas)
184 canvas.format = 'GIF'
193 def get_icon(min_lat, min_lon, max_lat, max_lon)
196 rat= Math.cos( ((max_lat + min_lat)/2.0) / 180.0 * 3.141592)
197 proj = OSM::Mercator.new((min_lat + max_lat) / 2, (max_lon + min_lon) / 2, (max_lat - min_lat) / width / rat, width, height)
201 gc = Magick::Draw.new
202 gc.stroke_linejoin('miter')
214 px = proj.x(p['longitude'])
215 py = proj.y(p['latitude'])
216 gc.line(px, py, oldpx, oldpy ) unless first
222 canvas = Magick::Image.new(width, height) {
223 self.background_color = 'white'
229 canvas.format = 'GIF'
230 return canvas.to_blob