Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/pull/3332'
Browse files Browse the repository at this point in the history
  • Loading branch information
tomhughes committed Sep 29, 2021
2 parents 7609c11 + 9ab15f3 commit cb10c10
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 82 deletions.
68 changes: 2 additions & 66 deletions app/controllers/api/tracepoints_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,75 +33,11 @@ def index
# get all the points
ordered_points = Tracepoint.bbox(bbox).joins(:trace).where(:gpx_files => { :visibility => %w[trackable identifiable] }).order("gpx_id DESC, trackid ASC, timestamp ASC")
unordered_points = Tracepoint.bbox(bbox).joins(:trace).where(:gpx_files => { :visibility => %w[public private] }).order("gps_points.latitude", "gps_points.longitude", "gps_points.timestamp")
points = ordered_points.union_all(unordered_points).offset(offset).limit(Settings.tracepoints_per_page).preload(:trace)

doc = XML::Document.new
doc.encoding = XML::Encoding::UTF_8
root = XML::Node.new "gpx"
root["version"] = "1.0"
root["creator"] = "OpenStreetMap.org"
root["xmlns"] = "http://www.topografix.com/GPX/1/0"

doc.root = root

# initialise these variables outside of the loop so that they
# stay in scope and don't get free'd up by the GC during the
# loop.
gpx_id = -1
trackid = -1
track = nil
trkseg = nil
anon_track = nil
anon_trkseg = nil
timestamps = false

points.each do |point|
if gpx_id != point.gpx_id
gpx_id = point.gpx_id
trackid = -1

if point.trace.trackable?
track = XML::Node.new "trk"
doc.root << track
timestamps = true

if point.trace.identifiable?
track << (XML::Node.new("name") << point.trace.name)
track << (XML::Node.new("desc") << point.trace.description)
track << (XML::Node.new("url") << url_for(:controller => "/traces", :action => "show", :display_name => point.trace.user.display_name, :id => point.trace.id))
end
else
# use the anonymous track segment if the user hasn't allowed
# their GPX points to be tracked.
timestamps = false
if anon_track.nil?
anon_track = XML::Node.new "trk"
doc.root << anon_track
end
track = anon_track
end
end

if trackid != point.trackid
if point.trace.trackable?
trkseg = XML::Node.new "trkseg"
track << trkseg
trackid = point.trackid
else
if anon_trkseg.nil?
anon_trkseg = XML::Node.new "trkseg"
anon_track << anon_trkseg
end
trkseg = anon_trkseg
end
end

trkseg << point.to_xml_node(:print_timestamp => timestamps)
end
@points = ordered_points.union_all(unordered_points).offset(offset).limit(Settings.tracepoints_per_page).preload(:trace)

response.headers["Content-Disposition"] = "attachment; filename=\"tracks.gpx\""

render :xml => doc.to_s
render :formats => [:gpx]
end
end
end
8 changes: 0 additions & 8 deletions app/models/tracepoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,4 @@ class Tracepoint < ApplicationRecord
validates :timestamp, :presence => true

belongs_to :trace, :foreign_key => "gpx_id"

def to_xml_node(print_timestamp: false)
el1 = XML::Node.new "trkpt"
el1["lat"] = lat.to_s
el1["lon"] = lon.to_s
el1 << (XML::Node.new("time") << timestamp.xmlschema) if print_timestamp
el1
end
end
79 changes: 79 additions & 0 deletions app/views/api/tracepoints/index.gpx.builder
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
xml.instruct!

xml.gpx("version" => "1.0",
"creator" => "OpenStreetMap.org",
"xmlns" => "http://www.topografix.com/GPX/1/0") do
# initialise these variables outside of the loop so that they
# stay in scope and don't get free'd up by the GC during the
# loop.
gpx_id = -1
trackid = -1
tracks = []
track = nil
trkseg = nil
anon_track = nil
anon_trkseg = nil

@points.each do |point|
if gpx_id != point.gpx_id
gpx_id = point.gpx_id
trackid = -1

if point.trace.trackable?
track = {}
track["trksegs"] = []
tracks << track

if point.trace.identifiable?
track["name"] = point.trace.name
track["desc"] = point.trace.description
track["url"] = url_for(:controller => "/traces", :action => "show", :display_name => point.trace.user.display_name, :id => point.trace.id)
end
else
# use the anonymous track segment if the user hasn't allowed
# their GPX points to be tracked.
if anon_track.nil?
anon_track = {}
anon_track["trksegs"] = []
tracks << anon_track
end
track = anon_track
end
end

if trackid != point.trackid
if point.trace.trackable?
trkseg = []
track["trksegs"] << trkseg
trackid = point.trackid
else
if anon_trkseg.nil?
anon_trkseg = []
anon_track["trksegs"] << anon_trkseg
end
trkseg = anon_trkseg
end
end

trkseg << point
end

tracks.each do |trk|
xml.trk do
if trk.key?("name")
xml.name trk["name"]
xml.desc trk["desc"]
xml.url trk["url"]
end
trk["trksegs"].each do |trksg|
xml.trkseg do
trksg.each do |tracepoint|
xml.trkpt("lat" => tracepoint.lat.to_s, "lon" => tracepoint.lon.to_s) do
xml.time tracepoint.timestamp.xmlschema if tracepoint.trace.trackable?
end
end
end
end
end
end
end
9 changes: 9 additions & 0 deletions test/controllers/api/tracepoints_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,5 +148,14 @@ def test_bbox_lat_mixedup
assert_equal "The minimum latitude must be less than the maximum latitude, but it wasn't", @response.body, "bbox: #{bbox}"
end
end

# Ensure the lat/lon is formatted as a decimal e.g. not 4.0e-05
def test_lat_lon_xml_format
create(:tracepoint, :latitude => (0.00004 * GeoRecord::SCALE).to_i, :longitude => (0.00008 * GeoRecord::SCALE).to_i)

get trackpoints_path(:bbox => "0,0,0.1,0.1")
assert_match(/lat="0.0000400"/, response.body)
assert_match(/lon="0.0000800"/, response.body)
end
end
end
8 changes: 0 additions & 8 deletions test/models/tracepoint_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,4 @@ def test_timestamp_required
tracepoint.timestamp = nil
assert_not tracepoint.valid?
end

# Ensure the lat/lon is formatted as a decimal e.g. not 4.0e-05
def test_lat_lon_xml_format
tracepoint = build(:tracepoint, :latitude => 0.00004 * GeoRecord::SCALE, :longitude => 0.00008 * GeoRecord::SCALE)

assert_match(/lat="0.0000400"/, tracepoint.to_xml_node.to_s)
assert_match(/lon="0.0000800"/, tracepoint.to_xml_node.to_s)
end
end

0 comments on commit cb10c10

Please sign in to comment.