Color-code, cluster and add icons to POI waypoints
A park4night/OsmAnd POI export (e.g. a p4n2gpx area export) tags every waypoint with a category and a per-category color/icon in its <extensions> block, all of which was previously thrown away — every waypoint rendered as the same plain red dot, unreadable once a file has a few thousand of them. Maptool::Gpx now captures category/color/icon (waypoint_style), matched by namespace URI rather than local element name: a p4n2gpx file carries both <osmand:icon> and <locus:icon> side by side, and REXML strips prefixes from Element#name, so both report as just "icon" — matching on that alone was silently picking the (useless) Locus drawable path instead of the OsmAnd category key. Regression test added for this. On the map: waypoints are colored by category (falling back to the plain track color for anything uncategorized), a small hand-drawn icon set (public/js/icons.js's POI_ICONS, rasterized to SDF sprites at runtime) draws a glyph on top for the categories it covers, the points source is clustered so a dense export collapses into count bubbles instead of a solid blob, and a legend in the side panel lists whichever categories are currently visible. Splitting each file's GeoJSON into a lines source and a points source (rather than one mixed source with a geometry-type filter per layer) was needed for clustering, since MapLibre's cluster support only understands a source made entirely of points.
This commit is contained in:
1 parent
708c08259b
commit
0b18dc018a
8 files changed
+434
-35
No files matched your search
@@ -39,6 +39,7 @@ module Maptool
|
||||
end
|
||||
|
||||
def self.waypoint_feature(wpt)
|
||||
ext = waypoint_style(wpt)
|
||||
{
|
||||
"type" => "Feature",
|
||||
"geometry" => { "type" => "Point", "coordinates" => coordinate(wpt) },
|
||||
@@ -47,11 +48,44 @@ module Maptool
|
||||
"name" => child_text(wpt, "name"),
|
||||
"description" => child_text(wpt, "desc"),
|
||||
"time" => child_text(wpt, "time"),
|
||||
"category" => child_text(wpt, "type"),
|
||||
"color" => ext[:color],
|
||||
"icon" => ext[:icon],
|
||||
},
|
||||
}
|
||||
end
|
||||
private_class_method :waypoint_feature
|
||||
|
||||
OSMAND_NAMESPACE = "https://osmand.net"
|
||||
private_constant :OSMAND_NAMESPACE
|
||||
|
||||
# POI exports (park4night via p4n2gpx, OsmAnd) tag each waypoint with a
|
||||
# category (<type>) and, in a vendor <extensions> block, a per-category
|
||||
# color and an OsmAnd icon key (e.g. "amenity_parking") — used to
|
||||
# color/icon-code the map instead of every waypoint rendering as the same
|
||||
# plain dot. Matched by namespace *URI*, not just local element name
|
||||
# (unlike point_extensions below, which only cares about local names):
|
||||
# a p4n2gpx export carries both an <osmand:icon> (a category key we can
|
||||
# actually render) and a <locus:icon> (a Locus-app-specific drawable
|
||||
# path) side by side — both strip down to the same local name "icon",
|
||||
# so matching on that alone picks whichever happens to come last.
|
||||
def self.waypoint_style(wpt)
|
||||
values = {}
|
||||
extensions = wpt.elements["extensions"]
|
||||
return values unless extensions
|
||||
|
||||
extensions.elements.each do |el|
|
||||
next unless el.namespace == OSMAND_NAMESPACE
|
||||
|
||||
case el.name
|
||||
when "color" then values[:color] = el.text&.strip
|
||||
when "icon" then values[:icon] = el.text&.strip
|
||||
end
|
||||
end
|
||||
values
|
||||
end
|
||||
private_class_method :waypoint_style
|
||||
|
||||
def self.track_feature(trk)
|
||||
lines = []
|
||||
all_points = []
|
||||
|
||||
Reference in new issue
Block a user