fix coord bug

This commit is contained in:
Graham McIntire 2025-10-19 09:06:58 -05:00
parent 1b638cf739
commit 5e3f0bc5cf
No known key found for this signature in database
5 changed files with 126 additions and 37 deletions

View file

@ -105,6 +105,21 @@ export class TrailManager {
) {
if (!this.showTrails) return;
// Validate coordinates before processing
if (
typeof lat !== 'number' ||
typeof lng !== 'number' ||
!isFinite(lat) ||
!isFinite(lng) ||
lat < -90 ||
lat > 90 ||
lng < -180 ||
lng > 180
) {
console.warn("Invalid coordinates provided to addPosition:", { markerId, lat, lng, timestamp });
return;
}
// Extract base callsign from markerId to group positions by callsign
const baseCallsign = this.extractBaseCallsign(markerId);
@ -253,29 +268,53 @@ export class TrailManager {
trailState.dots = [];
}
// Create new trail if we have at least 2 positions
// Create new trail if we have at least 2 positions with valid coordinates
if (trailState.positions.length >= 2) {
const latLngs: [number, number][] = trailState.positions.map((pos) => [pos.lat, pos.lng]);
// Filter out positions with invalid coordinates and create coordinate pairs
const latLngs: [number, number][] = trailState.positions
.filter((pos) => {
// Validate coordinates are finite numbers within valid ranges
return (
pos &&
typeof pos.lat === 'number' &&
typeof pos.lng === 'number' &&
isFinite(pos.lat) &&
isFinite(pos.lng) &&
pos.lat >= -90 &&
pos.lat <= 90 &&
pos.lng >= -180 &&
pos.lng <= 180
);
})
.map((pos) => [pos.lat, pos.lng]);
// Assign color if not already assigned
if (!trailState.color) {
trailState.color = this.assignTrailColor(baseCallsign, trailState.positions);
// Only create trail if we still have at least 2 valid positions after filtering
if (latLngs.length >= 2) {
// Assign color if not already assigned
if (!trailState.color) {
trailState.color = this.assignTrailColor(baseCallsign, trailState.positions);
}
// Create polyline with assigned color
// For historical positions (immediate=true), use higher opacity for better visibility
const polylineOptions: PolylineOptions = {
color: trailState.color,
weight: 3,
opacity: immediate ? 0.9 : 0.8,
smoothFactor: 1,
lineCap: "round",
lineJoin: "round",
className: "historical-trail-line",
};
try {
trailState.trail = L.polyline(latLngs, polylineOptions).addTo(this.trailLayer);
} catch (error) {
console.error("Error creating trail polyline for", baseCallsign, ":", error);
console.error("Invalid coordinates:", latLngs);
}
}
// Create polyline with assigned color
// For historical positions (immediate=true), use higher opacity for better visibility
const polylineOptions: PolylineOptions = {
color: trailState.color,
weight: 3,
opacity: immediate ? 0.9 : 0.8,
smoothFactor: 1,
lineCap: "round",
lineJoin: "round",
className: "historical-trail-line",
};
trailState.trail = L.polyline(latLngs, polylineOptions).addTo(this.trailLayer);
// Don't create additional dots here since historical positions are now shown as markers
trailState.dots = [];
}

View file

@ -1075,11 +1075,15 @@ let MapAPRSMap = {
// Add markers in chronological order
sortedPackets.forEach((packet) => {
self.addMarker({
...packet,
historical: true,
popup: packet.popup || self.buildPopupContent(packet),
});
try {
self.addMarker({
...packet,
historical: true,
popup: packet.popup || self.buildPopupContent(packet),
});
} catch (error) {
console.error("Error adding historical packet:", error, packet);
}
});
});
}
@ -1118,11 +1122,15 @@ let MapAPRSMap = {
// Add markers in chronological order
sortedPackets.forEach((packet) => {
self.addMarker({
...packet,
historical: true,
popup: packet.popup || self.buildPopupContent(packet),
});
try {
self.addMarker({
...packet,
historical: true,
popup: packet.popup || self.buildPopupContent(packet),
});
} catch (error) {
console.error("Error adding historical packet:", error, packet);
}
});
});
}
@ -1429,7 +1437,7 @@ let MapAPRSMap = {
// Validate coordinates
if (!isValidCoordinate(lat, lng)) {
console.warn("Invalid coordinates:", lat, lng);
console.warn("Invalid coordinates for marker:", { id: data.id, lat, lng, callsign: data.callsign });
return;
}

View file

@ -98,7 +98,7 @@ defmodule Aprsme.Cache do
opts
ttl_ms when is_integer(ttl_ms) and ttl_ms > 0 ->
ttl_seconds = Integer.ceil_div(ttl_ms, 1000) |> max(1)
ttl_seconds = ttl_ms |> Integer.ceil_div(1000) |> max(1)
Keyword.put(opts, :ttl, ttl_seconds)
ttl_ms when is_integer(ttl_ms) ->

View file

@ -50,9 +50,19 @@ defmodule AprsmeWeb.MapLive.DataBuilder do
{lat, lon, data_extended} = MapHelpers.get_coordinates(packet)
callsign = generate_callsign(packet)
if lat && lon && callsign != "" && callsign != nil do
packet_data = build_packet_map(packet, lat, lon, data_extended, locale)
# Validate coordinates and callsign before building packet data
if valid_coordinates?(lat, lon) && callsign != "" && callsign != nil do
packet_data = build_packet_map(packet, to_float(lat), to_float(lon), data_extended, locale)
Map.put(packet_data, "is_most_recent_for_callsign", is_most_recent_for_callsign)
else
# Log invalid data for debugging
if not valid_coordinates?(lat, lon) do
require Logger
Logger.debug("Invalid coordinates in packet #{get_packet_id(packet)}: lat=#{inspect(lat)}, lon=#{inspect(lon)}")
end
nil
end
end
@ -81,7 +91,8 @@ defmodule AprsmeWeb.MapLive.DataBuilder do
# Build minimal packet data without calling expensive build_packet_data
{lat, lon, _} = get_coordinates(packet)
if lat && lon do
# Validate coordinates are numeric and within valid ranges
if valid_coordinates?(lat, lon) do
# Use get_packet_field to get symbol information properly (includes data_extended fallback)
symbol_table_id = get_packet_field(packet, :symbol_table_id, "/")
symbol_code = get_packet_field(packet, :symbol_code, ">")
@ -97,8 +108,8 @@ defmodule AprsmeWeb.MapLive.DataBuilder do
%{
"id" => if(is_most_recent, do: "current_#{get_packet_id(packet)}", else: "hist_#{get_packet_id(packet)}"),
"lat" => lat,
"lng" => lon,
"lat" => to_float(lat),
"lng" => to_float(lon),
"callsign" => get_packet_field(packet, :sender, ""),
"symbol_table_id" => symbol_table_id,
"symbol_code" => symbol_code,
@ -110,9 +121,24 @@ defmodule AprsmeWeb.MapLive.DataBuilder do
"path" => get_packet_field(packet, :path, ""),
"popup" => build_simple_popup(packet, has_weather)
}
else
# Log invalid coordinates for debugging
require Logger
Logger.debug("Invalid coordinates in packet #{get_packet_id(packet)}: lat=#{inspect(lat)}, lon=#{inspect(lon)}")
nil
end
end
# Validate coordinates are numeric and within valid ranges
@spec valid_coordinates?(any(), any()) :: boolean()
defp valid_coordinates?(lat, lon) when is_number(lat) and is_number(lon) do
lat >= -90 and lat <= 90 and lon >= -180 and lon <= 180 and
:math.is_finite(lat) and :math.is_finite(lon)
end
defp valid_coordinates?(_, _), do: false
@doc """
Build packet data list for historical display.
Moved from historical_loader.ex.

View file

@ -216,7 +216,23 @@ defmodule AprsmeWeb.MapLive.HistoricalLoader do
# Process this batch and send to frontend
packet_data_list =
try do
DataBuilder.build_packet_data_list(historical_packets)
# Filter out packets with invalid coordinates before processing
valid_packets =
Enum.filter(historical_packets, fn packet ->
{lat, lon, _} = AprsmeWeb.Live.Shared.CoordinateUtils.get_coordinates(packet)
is_number(lat) and is_number(lon) and
lat >= -90 and lat <= 90 and lon >= -180 and lon <= 180 and
:math.is_finite(lat) and :math.is_finite(lon)
end)
if length(valid_packets) < length(historical_packets) do
Logger.debug(
"Filtered out #{length(historical_packets) - length(valid_packets)} packets with invalid coordinates"
)
end
DataBuilder.build_packet_data_list(valid_packets)
rescue
e ->
require Logger