diff --git a/components/map/Course.tsx b/components/map/Course.tsx
index 0b6180b..fbb2ed6 100644
--- a/components/map/Course.tsx
+++ b/components/map/Course.tsx
@@ -1,10 +1,12 @@
import { useEffect, useMemo } from 'react';
import { CircleMarker } from 'react-leaflet';
import AntPath from '../../components/map/AntPath';
+import MapWaypoint from './Waypoint';
import { CourseData } from '../../lib/gpx_parser';
export default function MapCourse({ map, course }: { map: any; course: CourseData }) {
const { trackpoints } = course?.tracks[0]?.segments[0] || { trackpoints: [] };
+ const waypoints = course?.waypoints || [];
const polyline = useMemo<[number, number][]>(() => trackpoints.map(({ lat, lon }) => [lat, lon]), [trackpoints]);
const first = polyline[0];
const last = polyline[polyline.length - 1];
@@ -22,6 +24,9 @@ export default function MapCourse({ map, course }: { map: any; course: CourseDat
{/* @ts-ignore */}
{last ? : null}
+ <>
+ {waypoints.map(({lat, lon, name}, i: number) => {name})}
+ >
>
);
}
diff --git a/components/map/Waypoint.tsx b/components/map/Waypoint.tsx
new file mode 100644
index 0000000..45c33f2
--- /dev/null
+++ b/components/map/Waypoint.tsx
@@ -0,0 +1,28 @@
+'use client';
+import L from 'leaflet';
+import { Marker, Popup } from 'react-leaflet';
+import MarkerIcon from '../../node_modules/leaflet/dist/images/marker-icon.png';
+import MarkerShadow from '../../node_modules/leaflet/dist/images/marker-shadow.png';
+import { ReactNode } from 'react';
+
+export default function MapWaypoint({ position, children }: { position: [number, number]; children?: ReactNode }) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/lib/gpx_parser.ts b/lib/gpx_parser.ts
index b2b739c..edcd028 100644
--- a/lib/gpx_parser.ts
+++ b/lib/gpx_parser.ts
@@ -3,7 +3,7 @@ type Coord = {
lon: number;
};
type Trackpoint = Coord & {
- ele: number;
+ ele?: number;
};
type Segment = {
trackpoints: Trackpoint[];
@@ -13,10 +13,17 @@ type Track = {
segments: Segment[];
};
type Routepoint = Coord;
-type Waypoint = Coord;
+type Route = {
+ name?: string;
+ routepoints: Routepoint[];
+};
+type Waypoint = Coord & {
+ name?: string;
+ ele?: number;
+};
export type CourseData = {
tracks: Track[];
- routePoints: Routepoint[];
+ routes: Route[];
waypoints: Waypoint[];
};
@@ -47,13 +54,22 @@ function getElValue(el: HTMLCollectionOf) {
return el[0].childNodes[0].nodeValue;
}
+function parseTrackpoint(el: Element): Trackpoint {
+ const trackpoint: Trackpoint = {
+ lat: parseFloat(el.getAttribute('lat')),
+ lon: parseFloat(el.getAttribute('lon')),
+ };
+ const ele = parseFloat(getElValue(el.getElementsByTagName('ele')));
+ if (!Number.isNaN(ele)) {
+ trackpoint.ele = ele;
+ }
+
+ return trackpoint;
+}
+
function parseTrackpoints(trackpoints: HTMLCollectionOf): Trackpoint[] {
return [
- ...elIter(trackpoints, (trackpoint) => ({
- lat: parseFloat(trackpoint.getAttribute('lat')),
- lon: parseFloat(trackpoint.getAttribute('lon')),
- ele: parseFloat(getElValue(trackpoint.getElementsByTagName('ele'))),
- })),
+ ...elIter(trackpoints, parseTrackpoint),
];
}
@@ -74,17 +90,45 @@ function parseTracks(tracks: HTMLCollectionOf): Track[] {
];
}
+function parseRoutepoints(routepoints: HTMLCollectionOf): Routepoint[] {
+ return [
+ ...elIter(routepoints, (routepoint) => ({
+ lat: parseFloat(routepoint.getAttribute('lat')),
+ lon: parseFloat(routepoint.getAttribute('lon')),
+ })),
+ ];
+}
+
+function parseRoutes(routes: HTMLCollectionOf): Route[] {
+ return [
+ ...elIter(routes, (route) => ({
+ name: getElValue(route.getElementsByTagName('name')),
+ routepoints: parseRoutepoints(route.getElementsByTagName('rtept')),
+ })),
+ ];
+}
+
+function parseWaypoints(waypoints: HTMLCollectionOf): Waypoint[] {
+ return [
+ ...elIter(waypoints, (waypoint) => ({
+ name: getElValue(waypoint.getElementsByTagName('name')),
+ lat: parseFloat(waypoint.getAttribute('lat')),
+ lon: parseFloat(waypoint.getAttribute('lon')),
+ })),
+ ];
+}
+
export function gpxDocument2obj(doc: Document): CourseData {
return {
tracks: parseTracks(doc.documentElement.getElementsByTagName('trk')),
- routePoints: [],
- waypoints: [],
+ routes: parseRoutes(doc.documentElement.getElementsByTagName('rte')),
+ waypoints: parseWaypoints(doc.documentElement.getElementsByTagName('wpt')),
};
}
export function getMapBounds(obj: CourseData) {
// TODO support all tracks and segments
- const points = [...obj.tracks[0].segments[0].trackpoints, ...obj.routePoints, ...obj.waypoints];
+ const points = [...obj.tracks[0].segments[0].trackpoints, ...obj.routes[0].routepoints, ...obj.waypoints];
const lats = points.map(({ lat }) => lat);
const lons = points.map(({ lon }) => lon);
return {