source: subversion/sites/rails_port/lib/gpx.rb @ 19899

Last change on this file since 19899 was 9376, checked in by tomhughes, 12 years ago

Rework GPX import daemon to use libxml2 for speed.

File size: 3.7 KB
Line 
1module GPX
2  class File
3    require "libxml"
4
5    include LibXML
6
7    attr_reader :possible_points
8    attr_reader :actual_points
9    attr_reader :tracksegs
10
11    def initialize(file)
12      @file = file
13    end
14
15    def points
16      @possible_points = 0
17      @actual_points = 0
18      @tracksegs = 0
19
20      @file.rewind
21
22      reader = XML::Reader.io(@file)
23
24      point = nil
25
26      while reader.read > 0
27        if reader.node_type == XML::Reader::TYPE_ELEMENT
28          if reader.name == "trkpt"
29            point = TrkPt.new(@tracksegs, reader["lat"].to_f, reader["lon"].to_f)
30            @possible_points += 1
31          elsif reader.name == "ele" and point
32            point.altitude = reader.read_string.to_f
33          elsif reader.name == "time" and point
34            point.timestamp = DateTime.parse(reader.read_string)
35          end
36        elsif reader.node_type == XML::Reader::TYPE_END_ELEMENT
37          if reader.name == "trkpt" and point and point.valid?
38            point.altitude ||= 0
39            yield point
40            @actual_points += 1
41          elsif reader.name == "trkseg"
42            @tracksegs += 1
43          end
44        end
45      end
46    end
47
48    def picture(min_lat, min_lon, max_lat, max_lon, num_points)
49      frames = 10
50      width = 250
51      height = 250
52      proj = OSM::Mercator.new(min_lat, min_lon, max_lat, max_lon, width, height)
53
54      linegc = Magick::Draw.new
55      linegc.stroke_linejoin('miter')
56      linegc.stroke_width(1)
57      linegc.stroke('#BBBBBB')
58      linegc.fill('#BBBBBB')
59
60      highlightgc = Magick::Draw.new
61      highlightgc.stroke_linejoin('miter')
62      highlightgc.stroke_width(3)
63      highlightgc.stroke('#000000')
64      highlightgc.fill('#000000')
65
66      images = []
67
68      frames.times do
69        image = Magick::Image.new(width, height) do |image|
70          image.background_color = 'white'
71          image.format = 'GIF'
72        end
73
74        images << image
75      end
76
77      oldpx = 0.0
78      oldpy = 0.0
79
80      first = true
81
82      m = 0
83      mm = 0
84      points do |p|
85        px = proj.x(p.longitude)
86        py = proj.y(p.latitude)
87
88        if m > 0
89          frames.times do |n|
90            if n == mm
91              gc = highlightgc.dup
92            else
93              gc = linegc.dup
94            end
95
96            gc.line(px, py, oldpx, oldpy)
97
98            gc.draw(images[n])
99          end
100        end
101
102        m += 1
103        if m > num_points.to_f / frames.to_f * (mm+1)
104          mm += 1
105        end
106
107        oldpy = py
108        oldpx = px
109      end
110
111      il = Magick::ImageList.new
112
113      images.each do |f|
114        il << f
115      end
116
117      il.delay = 50
118      il.format = 'GIF'
119
120      return il.to_blob
121    end
122
123    def icon(min_lat, min_lon, max_lat, max_lon)
124      width = 50
125      height = 50
126      proj = OSM::Mercator.new(min_lat, min_lon, max_lat, max_lon, width, height)
127
128      gc = Magick::Draw.new
129      gc.stroke_linejoin('miter')
130      gc.stroke_width(1)
131      gc.stroke('#000000')
132      gc.fill('#000000')
133
134      image = Magick::Image.new(width, height) do |image|
135        image.background_color = 'white'
136        image.format = 'GIF'
137      end
138
139      oldpx = 0.0
140      oldpy = 0.0
141
142      first = true
143
144      points do |p|
145        px = proj.x(p.longitude)
146        py = proj.y(p.latitude)
147
148        gc.dup.line(px, py, oldpx, oldpy).draw(image) unless first
149
150        first = false
151        oldpy = py
152        oldpx = px
153      end
154
155      return image.to_blob
156    end
157  end
158
159private
160
161  class TrkPt < Struct.new(:segment, :latitude, :longitude, :altitude, :timestamp)
162    def valid?
163      self.latitude and self.longitude and self.timestamp and
164      self.latitude >= -90 and self.latitude <= 90 and
165      self.longitude >= -180 and self.longitude <= 180
166    end
167  end
168end
Note: See TracBrowser for help on using the repository browser.