-
-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stop Grouping with Distance Range and (General) Directional filter #193
Changes from 4 commits
ebfea94
3accae1
0037a83
e72f154
24427df
eb5313f
4f70eaa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,181 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { useContext, useMemo } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { Company } from "hk-bus-eta"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import type { StopListEntry } from "hk-bus-eta"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import DbContext from "../context/DbContext"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { getDistance, getBearing } from "../utils"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
interface useStopGroupProps { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stopKeys: Array<[Company, string]>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
routeId : string | undefined; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
interface StopListEntryExtended extends StopListEntry { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
id : string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
distance : number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
routeStops : RouteStopCoSeq[]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
interface RouteStopCoSeq { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
routeKey : string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
co : Company; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
seq : number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// stopKey in format "<co>|<stopId>", e.g., "lightRail|LR140" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const useStopGroup = ({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stopKeys, routeId | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}: useStopGroupProps) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
db: { routeList, stopList }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} = useContext(DbContext); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// TODO: put these constants in AppContext user preference | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const DISTANCE_THRESHOLD = 50; // in metres, will recursively find stops within this number of metres, so keep it as small as possible. Never choose larger than 300m. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const BEARING_THRESHOLD = 45; // in degrees (°), acceptable deviation to the left or right of current bearing | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const STOP_LIST_LIMIT = 50; // max number of stops in a group, if more than that, the ETA list will be too long and meaningless | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const getDistanceStop = (a : StopListEntry, b : StopListEntry) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return getDistance(a.location, b.location); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const getBearingStops = (a : StopListEntry, b : StopListEntry) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return getBearing(a.location, b.location); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const getAllRouteStopsBearings = (routeStops : RouteStopCoSeq[]) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// routeStop example: {"routeKey":"101+1+KENNEDY TOWN+KWUN TONG (YUE MAN SQUARE)","co":"ctb","seq":12} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return routeStops.map(routeStop => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { routeKey, co, seq } = routeStop; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const stopLength = routeList[routeKey].stops[co].length; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let stopA, stopB; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if(seq == stopLength - 1) { // last stop | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// no next stop, hence no forward bearing, just use -1 as dummy value then discard it later | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return -1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stopA = stopList[routeList[routeKey].stops[co][seq]]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stopB = stopList[routeList[routeKey].stops[co][seq + 1]]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return getBearingStops(stopA, stopB); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}).filter(brng => brng !== -1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const routeStops : RouteStopCoSeq[]= []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if(routeId !== undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// StopDialog | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let targetRouteStops = routeList[routeId].stops; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stopKeys.forEach(([co, stopId]) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let seq = targetRouteStops[co]?.indexOf(stopId) ?? -1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if(seq != -1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
routeStops.push({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
routeKey : routeId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
co : co, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
seq : seq | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// SwipableStopList (saved stop list) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stopKeys.forEach(([co, stopId]) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Object.keys(routeList).forEach(routeKey => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let seq = routeList[routeKey]?.stops[co]?.indexOf(stopId) ?? -1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if(seq != -1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
routeStops.push({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
routeKey : routeKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
co : co, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
seq : seq | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const bearingTargets = getAllRouteStopsBearings(routeStops); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const isBearingInRange = (bearing : number) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if(BEARING_THRESHOLD >= 180 || bearingTargets.length == 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for(let i = 0; i < bearingTargets.length; ++i) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let bearingMin = bearingTargets[i] - BEARING_THRESHOLD; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let bearingMax = bearingTargets[i] + BEARING_THRESHOLD; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if(bearingMin < 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bearingMin += 360; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if(bearingMax > 360) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bearingMax -= 360; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if((bearingMin <= bearingMax && bearingMin <= bearing && bearing <= bearingMax) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|| (bearingMin > bearingMax && (bearingMin <= bearing || bearing <= bearingMax))) // crossing 0/360° mark, eg min=340°,max=020° | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optimize the The function definition is correct but can be optimized by removing the unnecessary else clause. - if(BEARING_THRESHOLD >= 180 || bearingTargets.length == 0) {
- return true;
- } else {
- for(let i = 0; i < bearingTargets.length; ++i) {
- let bearingMin = bearingTargets[i] - BEARING_THRESHOLD;
- let bearingMax = bearingTargets[i] + BEARING_THRESHOLD;
- if(bearingMin < 0)
- bearingMin += 360;
- if(bearingMax > 360)
- bearingMax -= 360;
- if((bearingMin <= bearingMax && bearingMin <= bearing && bearing <= bearingMax)
- || (bearingMin > bearingMax && (bearingMin <= bearing || bearing <= bearingMax))) // crossing 0/360° mark, eg min=340°,max=020°
- return true;
- }
- return false;
- }
+ if(BEARING_THRESHOLD >= 180 || bearingTargets.length == 0) return true;
+ for(let i = 0; i < bearingTargets.length; ++i) {
+ let bearingMin = bearingTargets[i] - BEARING_THRESHOLD;
+ let bearingMax = bearingTargets[i] + BEARING_THRESHOLD;
+ if(bearingMin < 0) bearingMin += 360;
+ if(bearingMax > 360) bearingMax -= 360;
+ if((bearingMin <= bearingMax && bearingMin <= bearing && bearing <= bearingMax)
+ || (bearingMin > bearingMax && (bearingMin <= bearing || bearing <= bearingMax))) // crossing 0/360° mark, eg min=340°,max=020°
+ return true;
+ }
+ return false; Committable suggestion
Suggested change
ToolsBiome
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const stopGroup = useMemo<Array<[Company, string]>>(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let stopListEntries : StopListEntryExtended[] = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const searchNearbyStops = (targetStopId : string, excludedStopIdList : string[]) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const targetStop = stopList[targetStopId]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Object.keys(stopList).filter((stopId) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// find stops that are within DISTANCE_THRESHOLD metres of target stop and along similar direction | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return getDistanceStop(targetStop, stopList[stopId]) <= DISTANCE_THRESHOLD && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// filter out stops that have not been added into excludeList before | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
!excludedStopIdList.includes(stopId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.reduce( (acc, stopId) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// get all the routes that has stop with this stopId | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const _routeStops = Object.entries(routeList).map(([routeKey, routeListEntry]) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const stops = routeListEntry.stops ?? {}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const companies = Object.keys(stops) as Company[]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for(let co of companies) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let stopPos = stops[co]?.indexOf(stopId) ?? -1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if(stopPos > -1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return { routeKey : routeKey, co : co, seq : stopPos } as RouteStopCoSeq; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return { routeKey : routeKey, co : 'ctb', seq : -1 } as RouteStopCoSeq; // use ctb as dummy value and seq = -1, will be discarded in next filter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.filter((_rs) => _rs.seq != -1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// if any of the routes passing this stop is facing same direction (+/- BEARING_THRESHOLD), add the stop to the list | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Note: once the stop is added, other routes not facing same direction but passing this stop will also be shown in ETA (most commonly seen in railway lines) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const bearings = getAllRouteStopsBearings(_routeStops); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if(bearings.find(b => isBearingInRange(b)) !== undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const thisStop : StopListEntryExtended = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
...stopList[stopId], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
id : stopId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
routeStops : _routeStops, // _routeStops.length must be > 0 here, as bearings.length must be > 0 to reach into this if-condition | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
distance : 0 // dummy value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
acc.push(thisStop); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return acc | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, [] as Array<StopListEntryExtended>); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// recursively search for nearby stops within thresholds (distance and bearing) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// stop searching when no new stops are found within range, or when stop list is getting too large | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stopKeys.forEach((stopKey) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const [, stopId] = stopKey; // [co, stopId] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stopListEntries = stopListEntries.concat(searchNearbyStops(stopId, stopListEntries.map((stop) => stop.id))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for(let i = 0; i < stopListEntries.length; ++i) { // use traditional for-loop as the length keeps expanding | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stopListEntries = stopListEntries.concat(searchNearbyStops(stopListEntries[i].id, stopListEntries.map((stop) => stop.id))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if(stopListEntries.length >= STOP_LIST_LIMIT) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// sort by distance from first stop in stopMap (stopKeys[0]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const _stopGroup : Array<[Company, string]> = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if(stopKeys.length > 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let [, stopId] = stopKeys[0]; // [co, stopId] but don't use this co | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stopListEntries = stopListEntries.map(stop => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
... stop, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
distance : getDistanceStop(stopList[stopId], stop) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}).sort((stopA, stopB) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return stopA.distance - stopB.distance | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stopListEntries.forEach((stopListEntry) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if(stopListEntry.routeStops.length > 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_stopGroup.push([stopListEntry.routeStops[0].co, stopListEntry.id]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return _stopGroup; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, [stopKeys, routeList, stopList]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check warning on line 178 in src/hooks/useStopGroup.tsx
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return stopGroup; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -34,6 +34,19 @@ export const getDistanceWithUnit = (distanceInMetre: number) => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const getBearing = (a: GeoLocation, b: GeoLocation) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Reference: https://www.movable-type.co.uk/scripts/latlong.html | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const φ1 = a.lat * Math.PI / 180; // φ, λ = lat, lon in radians | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const φ2 = b.lat * Math.PI / 180; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const λ1 = a.lng * Math.PI / 180; // φ, λ = lat, lon in radians | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const λ2 = b.lng * Math.PI / 180; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const y = Math.sin(λ2 - λ1) * Math.cos(φ2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const x = Math.cos(φ1) * Math.sin(φ2) - Math.sin(φ1) * Math.cos(φ2) * Math.cos(λ2-λ1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const θ = Math.atan2(y, x); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const brng = (θ * 180 / Math.PI + 360) % 360; // in degrees | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return brng; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+37
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optimize variable declarations and add comments for clarity. The function is correctly implemented but can be optimized and improved for readability by combining the variable declarations and adding comments to explain the steps. export const getBearing = (a: GeoLocation, b: GeoLocation) => {
// Reference: https://www.movable-type.co.uk/scripts/latlong.html
- const φ1 = a.lat * Math.PI / 180; // φ, λ = lat, lon in radians
- const φ2 = b.lat * Math.PI / 180;
- const λ1 = a.lng * Math.PI / 180; // φ, λ = lat, lon in radians
- const λ2 = b.lng * Math.PI / 180;
- const y = Math.sin(λ2 - λ1) * Math.cos(φ2);
- const x = Math.cos(φ1) * Math.sin(φ2) - Math.sin(φ1) * Math.cos(φ2) * Math.cos(λ2-λ1);
- const θ = Math.atan2(y, x);
- const brng = (θ * 180 / Math.PI + 360) % 360; // in degrees
- return brng;
+ const φ1 = a.lat * Math.PI / 180, φ2 = b.lat * Math.PI / 180;
+ const λ1 = a.lng * Math.PI / 180, λ2 = b.lng * Math.PI / 180;
+
+ // Calculate the differences
+ const Δλ = λ2 - λ1;
+ const y = Math.sin(Δλ) * Math.cos(φ2);
+ const x = Math.cos(φ1) * Math.sin(φ2) - Math.sin(φ1) * Math.cos(φ2) * Math.cos(Δλ);
+
+ // Calculate the bearing
+ const θ = Math.atan2(y, x);
+ return (θ * 180 / Math.PI + 360) % 360; // in degrees
}; Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const DEFAULT_GEOLOCATION: GeoLocation = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
lat: 22.302711, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
lng: 114.177216, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optimize the
getAllRouteStopsBearings
Function.The function definition is correct but can be optimized by removing the unnecessary else clause.
Committable suggestion
Tools
Biome