starts transition to maplibre
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { page } from "$app/stores";
|
||||
import { currentUser } from "$lib/stores/user_store";
|
||||
import { get } from "svelte/store";
|
||||
|
||||
export function formatTimeHHMM(minutes?: number) {
|
||||
|
||||
216
web/src/lib/util/geojson_util.ts
Normal file
216
web/src/lib/util/geojson_util.ts
Normal file
@@ -0,0 +1,216 @@
|
||||
import type { BBox, Feature, FeatureCollection, GeoJSON, GeoJsonObject, GeometryCollection, Position } from "geojson";
|
||||
|
||||
export function bbox(
|
||||
geojson: GeoJSON,
|
||||
): BBox {
|
||||
if (geojson.bbox != null) {
|
||||
return geojson.bbox;
|
||||
}
|
||||
const result: BBox = [Infinity, Infinity, -Infinity, -Infinity];
|
||||
let startPoint: Position, endPoint: Position;
|
||||
coordEach(geojson, (coord) => {
|
||||
startPoint ??= [coord[0], coord[1]];
|
||||
endPoint = coord;
|
||||
if (result[0] > coord[0]) {
|
||||
result[0] = coord[0];
|
||||
}
|
||||
if (result[1] > coord[1]) {
|
||||
result[1] = coord[1];
|
||||
}
|
||||
if (result[2] < coord[0]) {
|
||||
result[2] = coord[0];
|
||||
}
|
||||
if (result[3] < coord[1]) {
|
||||
result[3] = coord[1];
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function findStartAndEndPoints(geojson: GeoJsonObject): Position[] {
|
||||
const startEndPoints: Position[] = [];
|
||||
|
||||
(geojson as FeatureCollection).features.forEach((feature) => {
|
||||
const geometry = feature.geometry;
|
||||
|
||||
if (geometry.type === "LineString") {
|
||||
const coords = geometry.coordinates as number[][];
|
||||
const start: [number, number] = [coords[0][0], coords[0][1]]; // First point
|
||||
const end: [number, number] = [
|
||||
coords[coords.length - 1][0],
|
||||
coords[coords.length - 1][1],
|
||||
]; // Last point
|
||||
startEndPoints.push(start);
|
||||
startEndPoints.push(end)
|
||||
} else if (geometry.type === "MultiLineString") {
|
||||
const coords = geometry.coordinates as number[][][];
|
||||
const start: [number, number] = [
|
||||
coords[0][0][0],
|
||||
coords[0][0][1],
|
||||
]; // First point of the first line
|
||||
const lastLine = coords[coords.length - 1];
|
||||
const end: [number, number] = [
|
||||
lastLine[lastLine.length - 1][0],
|
||||
lastLine[lastLine.length - 1][1],
|
||||
]; // Last point of the last line
|
||||
startEndPoints.push(start);
|
||||
startEndPoints.push(end)
|
||||
} else {
|
||||
console.warn(
|
||||
`Geometry type ${geometry.type} is not supported for start/end point extraction.`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return startEndPoints;
|
||||
}
|
||||
|
||||
function coordEach(geojson: GeoJSON, callback: (
|
||||
currentCoord: number[],
|
||||
coordIndex: number,
|
||||
featureIndex: number,
|
||||
multiFeatureIndex: number,
|
||||
geometryIndex: number
|
||||
) => void | false,
|
||||
excludeWrapCoord?: boolean,) {
|
||||
// Handles null Geometry -- Skips this GeoJSON
|
||||
if (geojson === null) return;
|
||||
var j,
|
||||
k,
|
||||
l,
|
||||
geometry,
|
||||
stopG,
|
||||
coords,
|
||||
geometryMaybeCollection,
|
||||
wrapShrink = 0,
|
||||
coordIndex = 0,
|
||||
isGeometryCollection,
|
||||
type = geojson.type,
|
||||
isFeatureCollection = type === "FeatureCollection",
|
||||
isFeature = type === "Feature",
|
||||
stop = isFeatureCollection ? (geojson as FeatureCollection).features.length : 1;
|
||||
|
||||
for (var featureIndex = 0; featureIndex < stop; featureIndex++) {
|
||||
geometryMaybeCollection = isFeatureCollection
|
||||
? (geojson as FeatureCollection).features[featureIndex].geometry
|
||||
: isFeature
|
||||
? (geojson as Feature).geometry
|
||||
: geojson;
|
||||
isGeometryCollection = geometryMaybeCollection
|
||||
? geometryMaybeCollection.type === "GeometryCollection"
|
||||
: false;
|
||||
stopG = isGeometryCollection
|
||||
? (geometryMaybeCollection as GeometryCollection).geometries.length
|
||||
: 1;
|
||||
|
||||
for (var geomIndex = 0; geomIndex < stopG; geomIndex++) {
|
||||
var multiFeatureIndex = 0;
|
||||
var geometryIndex = 0;
|
||||
geometry = isGeometryCollection
|
||||
? (geometryMaybeCollection as GeometryCollection).geometries[geomIndex]
|
||||
: geometryMaybeCollection;
|
||||
|
||||
// Handles null Geometry -- Skips this geometry
|
||||
if (geometry === null) continue;
|
||||
coords = (geometry as any).coordinates;
|
||||
var geomType = geometry.type;
|
||||
|
||||
wrapShrink =
|
||||
excludeWrapCoord &&
|
||||
(geomType === "Polygon" || geomType === "MultiPolygon")
|
||||
? 1
|
||||
: 0;
|
||||
|
||||
switch (geomType) {
|
||||
case null:
|
||||
break;
|
||||
case "Point":
|
||||
if (
|
||||
callback(
|
||||
coords,
|
||||
coordIndex,
|
||||
featureIndex,
|
||||
multiFeatureIndex,
|
||||
geometryIndex
|
||||
) === false
|
||||
)
|
||||
return false;
|
||||
coordIndex++;
|
||||
multiFeatureIndex++;
|
||||
break;
|
||||
case "LineString":
|
||||
case "MultiPoint":
|
||||
for (j = 0; j < coords.length; j++) {
|
||||
if (
|
||||
callback(
|
||||
coords[j],
|
||||
coordIndex,
|
||||
featureIndex,
|
||||
multiFeatureIndex,
|
||||
geometryIndex
|
||||
) === false
|
||||
)
|
||||
return false;
|
||||
coordIndex++;
|
||||
if (geomType === "MultiPoint") multiFeatureIndex++;
|
||||
}
|
||||
if (geomType === "LineString") multiFeatureIndex++;
|
||||
break;
|
||||
case "Polygon":
|
||||
case "MultiLineString":
|
||||
for (j = 0; j < coords.length; j++) {
|
||||
for (k = 0; k < coords[j].length - wrapShrink; k++) {
|
||||
if (
|
||||
callback(
|
||||
coords[j][k],
|
||||
coordIndex,
|
||||
featureIndex,
|
||||
multiFeatureIndex,
|
||||
geometryIndex
|
||||
) === false
|
||||
)
|
||||
return false;
|
||||
coordIndex++;
|
||||
}
|
||||
if (geomType === "MultiLineString") multiFeatureIndex++;
|
||||
if (geomType === "Polygon") geometryIndex++;
|
||||
}
|
||||
if (geomType === "Polygon") multiFeatureIndex++;
|
||||
break;
|
||||
case "MultiPolygon":
|
||||
for (j = 0; j < coords.length; j++) {
|
||||
geometryIndex = 0;
|
||||
for (k = 0; k < coords[j].length; k++) {
|
||||
for (l = 0; l < coords[j][k].length - wrapShrink; l++) {
|
||||
if (
|
||||
callback(
|
||||
coords[j][k][l],
|
||||
coordIndex,
|
||||
featureIndex,
|
||||
multiFeatureIndex,
|
||||
geometryIndex
|
||||
) === false
|
||||
)
|
||||
return false;
|
||||
coordIndex++;
|
||||
}
|
||||
geometryIndex++;
|
||||
}
|
||||
multiFeatureIndex++;
|
||||
}
|
||||
break;
|
||||
case "GeometryCollection":
|
||||
for (j = 0; j < (geometry as GeometryCollection).geometries.length; j++)
|
||||
if (
|
||||
coordEach((geometry as GeometryCollection).geometries[j], callback, excludeWrapCoord) ===
|
||||
false
|
||||
)
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unknown Geometry Type");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,21 +2,22 @@ import GPX from "$lib/models/gpx/gpx";
|
||||
import { Trail } from "$lib/models/trail";
|
||||
import { Waypoint } from "$lib/models/waypoint";
|
||||
import { currentUser } from "$lib/stores/user_store";
|
||||
import { kml, tcx } from "$lib/vendor/toGeoJSON/toGeoJSON";
|
||||
import { gpx, kml, tcx } from "$lib/vendor/toGeoJSON/toGeoJSON";
|
||||
import cryptoRandomString from "crypto-random-string";
|
||||
import { get } from "svelte/store";
|
||||
//@ts-ignore
|
||||
import EasyFit from "$lib/vendor/easy-fit/easy-fit"
|
||||
import { browser } from "$app/environment";
|
||||
import Track from "$lib/models/gpx/track";
|
||||
import TrackSegment from "$lib/models/gpx/track-segment";
|
||||
import GPXWaypoint from "$lib/models/gpx/waypoint";
|
||||
import { browser } from "$app/environment";
|
||||
import * as xmldom from 'xmldom'
|
||||
import type { Feature, FeatureCollection, GeoJsonProperties, Position } from 'geojson';
|
||||
import EasyFit from "$lib/vendor/easy-fit/easy-fit";
|
||||
import type { GeoJSON, Feature, FeatureCollection, GeoJsonProperties, Position } from 'geojson';
|
||||
import * as xmldom from 'xmldom';
|
||||
import { bbox } from "./geojson_util";
|
||||
|
||||
|
||||
export async function gpx2trail(gpxString: string, fallbackName?: string) {
|
||||
|
||||
|
||||
const gpx = await GPX.parse(gpxString);
|
||||
|
||||
if (gpx instanceof Error) {
|
||||
@@ -281,4 +282,13 @@ export function isFITFile(buffer: ArrayBuffer) {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function toGeoJson(gpxData: string) {
|
||||
const parser = browser ? new DOMParser() : new xmldom.DOMParser();
|
||||
const geojson = gpx(
|
||||
parser.parseFromString(gpxData, "text/xml"),
|
||||
) as GeoJSON;
|
||||
geojson.bbox = bbox(geojson)
|
||||
return geojson
|
||||
}
|
||||
44
web/src/lib/util/maplibre_util.ts
Normal file
44
web/src/lib/util/maplibre_util.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import type { Waypoint } from "$lib/models/waypoint";
|
||||
import M from "maplibre-gl";
|
||||
|
||||
export class FontawesomeMarker extends M.Marker {
|
||||
constructor(options: { icon: string, fontSize?: string, width?: number, backgroundColor?: string, fontColor?: string }, markerOptions?: M.MarkerOptions) {
|
||||
const element = document.createElement('div')
|
||||
element.className = `cursor-pointer flex items-center justify-center w-${options.width ?? 7} aspect-square bg-${options.backgroundColor ?? "gray-500"} rounded-full text-${options.fontSize ?? "normal"}`
|
||||
super({ element: element, ...markerOptions });
|
||||
|
||||
const {
|
||||
icon,
|
||||
} = options
|
||||
|
||||
const iconElementString = `<i class="text-${options.fontColor ?? "white"} ${icon}"></i>`
|
||||
this._element.insertAdjacentHTML('beforeend', iconElementString)
|
||||
}
|
||||
}
|
||||
|
||||
export function createMarkerFromWaypoint(waypoint: Waypoint, onDragEnd?: (marker: M.Marker) => void): FontawesomeMarker {
|
||||
const marker = new FontawesomeMarker({
|
||||
icon: `fa fa-${waypoint.icon}`,
|
||||
}, {
|
||||
draggable: onDragEnd != null,
|
||||
color: "#6b7280"
|
||||
|
||||
})
|
||||
const popup = new M.Popup({ offset: 25, closeButton: false }).setHTML(
|
||||
"<b>" +
|
||||
waypoint.name +
|
||||
"</b>" +
|
||||
(waypoint.description && waypoint.description.length > 0
|
||||
? "<br>" + waypoint.description
|
||||
: ""),
|
||||
);
|
||||
marker
|
||||
.setLngLat([waypoint.lon, waypoint.lat])
|
||||
.setPopup(popup)
|
||||
|
||||
if (onDragEnd) {
|
||||
marker.on("dragend", () => onDragEnd(marker));
|
||||
}
|
||||
|
||||
return marker;
|
||||
}
|
||||
Reference in New Issue
Block a user