ride with gps · explore · time zone

i have forty minutes.

draw a zone. give it a time. explore finds the ride, or builds one.

stage · try it ↗ rails 23884 rails 23892 frontend 7051 frontend 7061 built on: routes through every point ↗

40
minutes

drag the ring, tap a stop, or use the arrows

01 · from here

the rides you can finish.

drop a start. explore keeps only the rides through it that fit your minutes, hills counted, at your pace.

or click the map to start anywhere. routes come live from the stage build.

—
rides through your start
—
fit your minutes
—
longest that fits

02 · inside the lines

draw a shape. rides that stay in.

click the map to drop corners, click the first to close. explore keeps the rides that stay inside for nine tenths of their length, then cuts them to your minutes.

0 corners

pick a shape, or draw your own.

—
rides in the box
—
stay inside the lines
—
fit your minutes

03 · build a loop

nothing fits? make one.

explore takes two routes through your start that cross, rides out on one and back on the other, and cuts the loop to your minutes.

from your start in 01, at your pace.

04 · ride it

then you go.

this is the real thing on the stage build. a clock under the search. a loop panel. a saved route, pinned, one tap from your phone.

the clock popover on explore: i have 40 minutes, presets, at your usual 10 mph, from a start point or an area i draw, build a loop
the clock. under the search box. tap it, say how long, pick where.
loops built for you: five loops listed with distance, climb and minutes, and one drawn on the map
the loops. five, built from routes that cross near your start. tap one, it draws.
a saved route page titled 40 min loop from portland, marked saved, with a toast: loop saved and pinned, want to change anything? edit it in the planner
the ride. saved as your route, pinned to your phone. want to change anything? edit it in the planner.

05 · how it finds them

from here

  1. every public route within 500 m of your start.
  2. how long each takes at your pace. every 100 m of climbing counts like an extra kilometre.
  3. keep the ones that finish inside your minutes and are not over too soon.
  4. closest fit first.

inside the lines

  1. every route that starts in the box around your shape.
  2. measure how much of each stays inside the shape.
  3. keep the ones that stay in for nine tenths of their length.
  4. then the same time cut as from here.

build a loop

  1. the thirty best routes through your start, up to three times your budget long.
  2. walk out along one and look for a spot where another passes within 60 m.
  3. out on the first, back on the second. keep loops that use half to all of your minutes and do not double back.
  4. the best five.

is this real? yes. the routes on this page come live from the stage build as you change things, and the maths is the same the server runs. the server does it faster, with full tracks.

for engineers

time budget

GET /explore.json?lat&lng&radius=500&minutes=40[&speed=20]
→ length_min = 0.5 × budget, length_max = budget, plus a painless filter
  distance + elevation_gain × 10 ≤ budget   (budget = speed_kmh × minutes / 60 × 1000)
→ meta.explore.time_box = { minutes, speed_kmh, speed_source: param|history|default, climb_factor: 10, distance_budget }
   speed_source history = median avg_speed of your last 20 gps rides

inside the lines

GET /explore.json?area=lat,lng|lat,lng|lat,lng[|…]&minutes=40      (3 to 20 corners)
→ the polygon is filled with H3 res-10 hexes (cap 17,000 ≈ 15 km × 15 km, sampled to 1,024 terms)
→ elasticsearch containment: min_match_containment 0.9 (area_containment 0.5..1.0 to tune)
→ meta.explore.area = { vertices, hex_count, min_containment, centroid, bounding_box }
   q cannot combine with area (both use the es score)

build a loop

GET /explore/stitch.json?lat&lng&minutes=40[&speed][&radius=500]
→ 30 candidates ≤ 3 × budget · junction ≤ 60 m · leg ≥ 1 km · overlap ≤ 35 % · target 0.9 × budget · best 5
→ { stitches: [ { legs: [ { route_id, from_index, to_index, reversed, distance, elevation_gain } ], distance,
     elevation_gain, effective_distance, estimated_minutes, junction, overlap_pct, polyline } ], candidates: [...] }
   the polyline is plain google lat/lng at 1e-5 (two values per point)

POST /explore/stitch/save.json   { legs, name?, minutes, start, junction? }
→ 201 { route: { id, url, name, distance, elevation_gain, visibility, pinned: true }, sources }
   rebuilt from the two source tracks, private, owned by you, pinned. 401 signed out, 400 bad legs.

the polyline

route simplified_polyline: SIX delta ints per point: y ×1e-5, x ×1e-5, d (m ×1e-2), e (m ×1e-2), S ×1e-1, R ×1e-1
this page decodes it in the browser and uses d for length and e for climb, exactly as rwgps-ui does.