<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://rodionov.cc/tags/tech/</id>
  <title>Alexander Rodionov - pages tagged with tech</title>
  <updated>2025-11-20T13:29:05.061032+00:00</updated>
  <author>
    <name>Alexander Rodionov</name>
  </author>
  <link href="https://rodionov.cc/tags/tech/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="https://rodionov.cc/tags/tech/" rel="alternate" type="text/html"/>
  <entry>
    <id>https://rodionov.cc/walk-tracks/</id>
    <title>GPX walk tracks</title>
    <updated>2025-11-20T16:26:03+03:00</updated>
    <content type="html">&lt;p&gt;&lt;a href="https://files.tandav.me/img/blog/large/Screenshot-2024-04-02-220223.png"&gt;
&lt;img src="https://files.tandav.me/img/blog/thumbnails/Screenshot-2024-04-02-220223.png" alt="Screenshot of GPX route in browser using gpx.studio iframe. A route is in Saburtalo district of Tbilisi, Georgia" &gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I exported information about walking tracks from Apple Watch (Apple Health), there is a standard GPX format. There is no way to automate the export as Apple doesn't give a way (privacy blah blah blah). Maybe in the future I will do tracks through some other application where I don't need to unload the whole history with a huge archive every time.&lt;/p&gt;
&lt;p&gt;Here is a python script that searches for faraway from current home tracks. (I don't worry about past rental places).&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-python"&gt;import functools
import shutil
import gpxpy
import tqdm
import gpxpy.gpx
from pathlib import Path
from geopy.distance import geodesic

home_coordinates = 0.0, 0.0  # redacted

@functools.cache
def gpx_meters_from_point(
    gpx_path: str,
    point: tuple[float, float],
    min_meters: float = 100,
) -&amp;gt; float:
    with open(gpx_path) as gpx_file:
        gpx = gpxpy.parse(gpx_file)

    meters = None

    for track in gpx.tracks:
        for segment in track.segments:
            for _point in segment.points:
                _meters = geodesic((_point.latitude, _point.longitude), point).meters
                meters = _meters if meters is None else min(meters, _meters)
    if meters is None:
        raise ValueError(f'no points found in gpx file {gpx_path}')
    return meters
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Copy to a public folder (which is then copied to the server) tracks that are further than 3000 meters:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-python"&gt;gpx_dir = Path('/Users/tandav/Desktop/apple_health_export/workout-routes')
gpx_public_dir = Path('/Users/tandav/docs/files-tandav-me/routes/routes/gpx')
gpx_files = list(gpx_dir.glob('*.gpx'))

for p in tqdm.tqdm(gpx_files):
    if gpx_meters_from_point(p, home_coordinates) &amp;lt; 3000:
        continue
    shutil.copy(p, gpx_public_dir / p.name)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is &lt;a href="https://gpx.studio/"&gt;gpx.studio&lt;/a&gt; which has ability to &lt;a href="https://gpx.studio/about.html#embed"&gt;render gpx filex from your server in iframe&lt;/a&gt;. But you have to setup CORS headers. Here is headers for Caddy:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-Caddyfile"&gt;files.tandav.me {
    root * /srv

    @gpxFiles {
        path *.gpx
    }
    header @gpxFiles Access-Control-Allow-Origin &amp;quot;https://gpx.studio&amp;quot;

    file_server {
        browse
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The list of my walk tracks is at &lt;a href="https://files.tandav.me/walk-tracks/"&gt;files.tandav.me/walk-tracks/&lt;/a&gt;. A screenshot of some walk track is at the beggining of the post.&lt;/p&gt;</content>
    <link href="https://rodionov.cc/walk-tracks/"/>
    <summary>Python code to analyze GPX files from apple watch for walk tracks</summary>
    <published>2024-04-02T21:35:00+03:00</published>
  </entry>
</feed>
