Extract shared extractWaypoints into @trails-cool/gpx
Both new.tsx and api.sessions.ts had duplicated track-segment waypoint extraction logic. Moved to packages/gpx as extractWaypoints(gpxData) — uses <wpt> elements when present, falls back to start of each track segment + end of last. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e0f7c5b806
commit
cc90c32a0e
4 changed files with 39 additions and 50 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import { data } from "react-router";
|
||||
import type { Route } from "./+types/api.sessions";
|
||||
import { createSession, listSessions } from "~/lib/sessions";
|
||||
import { parseGpxAsync } from "@trails-cool/gpx";
|
||||
import { parseGpxAsync, extractWaypoints } from "@trails-cool/gpx";
|
||||
import { withDb } from "@trails-cool/db";
|
||||
|
||||
export async function action({ request }: Route.ActionArgs) {
|
||||
|
|
@ -23,29 +23,8 @@ export async function action({ request }: Route.ActionArgs) {
|
|||
if (gpx) {
|
||||
try {
|
||||
const gpxData = await parseGpxAsync(gpx);
|
||||
// Use explicit waypoints if present, otherwise extract from track segments
|
||||
if (gpxData.waypoints.length > 0) {
|
||||
initialWaypoints = gpxData.waypoints;
|
||||
} else if (gpxData.tracks.length > 0) {
|
||||
const extracted: Array<{ lat: number; lon: number }> = [];
|
||||
for (const seg of gpxData.tracks) {
|
||||
if (seg.length === 0) continue;
|
||||
const first = seg[0]!;
|
||||
const prev = extracted[extracted.length - 1];
|
||||
if (!prev || prev.lat !== first.lat || prev.lon !== first.lon) {
|
||||
extracted.push({ lat: first.lat, lon: first.lon });
|
||||
}
|
||||
}
|
||||
const lastSeg = gpxData.tracks[gpxData.tracks.length - 1]!;
|
||||
if (lastSeg.length > 0) {
|
||||
const last = lastSeg[lastSeg.length - 1]!;
|
||||
const prev = extracted[extracted.length - 1];
|
||||
if (!prev || prev.lat !== last.lat || prev.lon !== last.lon) {
|
||||
extracted.push({ lat: last.lat, lon: last.lon });
|
||||
}
|
||||
}
|
||||
initialWaypoints = extracted;
|
||||
}
|
||||
const wps = extractWaypoints(gpxData);
|
||||
if (wps.length > 0) initialWaypoints = wps;
|
||||
} catch {
|
||||
// Continue with empty session if GPX is invalid
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { redirect, data } from "react-router";
|
||||
import type { Route } from "./+types/new";
|
||||
import { createSession, initializeSessionWithWaypoints } from "~/lib/sessions";
|
||||
import { parseGpxAsync } from "@trails-cool/gpx";
|
||||
import { parseGpxAsync, extractWaypoints } from "@trails-cool/gpx";
|
||||
import { checkRateLimit } from "~/lib/rate-limit";
|
||||
|
||||
export async function loader({ request }: Route.LoaderArgs) {
|
||||
|
|
@ -36,31 +36,7 @@ export async function loader({ request }: Route.LoaderArgs) {
|
|||
try {
|
||||
const gpx = decodeURIComponent(gpxEncoded);
|
||||
const gpxData = await parseGpxAsync(gpx);
|
||||
// Use explicit waypoints if present, otherwise extract from track segments
|
||||
let waypoints = gpxData.waypoints;
|
||||
if (waypoints.length === 0 && gpxData.tracks.length > 0) {
|
||||
const extracted: Array<{ lat: number; lon: number }> = [];
|
||||
for (const seg of gpxData.tracks) {
|
||||
if (seg.length === 0) continue;
|
||||
const first = seg[0]!;
|
||||
// Deduplicate: skip if same as previous waypoint
|
||||
const prev = extracted[extracted.length - 1];
|
||||
if (!prev || prev.lat !== first.lat || prev.lon !== first.lon) {
|
||||
extracted.push({ lat: first.lat, lon: first.lon });
|
||||
}
|
||||
}
|
||||
// Add the end of the last segment
|
||||
const lastSeg = gpxData.tracks[gpxData.tracks.length - 1]!;
|
||||
if (lastSeg.length > 0) {
|
||||
const last = lastSeg[lastSeg.length - 1]!;
|
||||
const prev = extracted[extracted.length - 1];
|
||||
if (!prev || prev.lat !== last.lat || prev.lon !== last.lon) {
|
||||
extracted.push({ lat: last.lat, lon: last.lon });
|
||||
}
|
||||
}
|
||||
waypoints = extracted;
|
||||
}
|
||||
initializeSessionWithWaypoints(session.id, waypoints);
|
||||
initializeSessionWithWaypoints(session.id, extractWaypoints(gpxData));
|
||||
} catch {
|
||||
// Continue with empty session if GPX is invalid
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
export { parseGpxAsync } from "./parse.ts";
|
||||
export { generateGpx } from "./generate.ts";
|
||||
export { extractWaypoints } from "./waypoints.ts";
|
||||
export type { GpxData, TrackPoint, ElevationProfile } from "./types.ts";
|
||||
|
|
|
|||
33
packages/gpx/src/waypoints.ts
Normal file
33
packages/gpx/src/waypoints.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import type { GpxData } from "./types.ts";
|
||||
|
||||
/**
|
||||
* Extract waypoints from parsed GPX data.
|
||||
* Uses explicit <wpt> elements if present, otherwise extracts the start
|
||||
* of each track segment + end of the last segment.
|
||||
*/
|
||||
export function extractWaypoints(gpxData: GpxData): Array<{ lat: number; lon: number; name?: string }> {
|
||||
if (gpxData.waypoints.length > 0) return gpxData.waypoints;
|
||||
if (gpxData.tracks.length === 0) return [];
|
||||
|
||||
const result: Array<{ lat: number; lon: number }> = [];
|
||||
for (const seg of gpxData.tracks) {
|
||||
if (seg.length === 0) continue;
|
||||
const first = seg[0]!;
|
||||
const prev = result[result.length - 1];
|
||||
if (!prev || prev.lat !== first.lat || prev.lon !== first.lon) {
|
||||
result.push({ lat: first.lat, lon: first.lon });
|
||||
}
|
||||
}
|
||||
|
||||
// Add end of last segment
|
||||
const lastSeg = gpxData.tracks[gpxData.tracks.length - 1]!;
|
||||
if (lastSeg.length > 0) {
|
||||
const last = lastSeg[lastSeg.length - 1]!;
|
||||
const prev = result[result.length - 1];
|
||||
if (!prev || prev.lat !== last.lat || prev.lon !== last.lon) {
|
||||
result.push({ lat: last.lat, lon: last.lon });
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue