Skip to content

Commit

Permalink
feat: change car marker to be chevron with heading similar to google …
Browse files Browse the repository at this point in the history
…maps navigation (#207)
  • Loading branch information
regeter authored Feb 10, 2025
1 parent ea58ed0 commit 20cb34a
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 37 deletions.
61 changes: 39 additions & 22 deletions src/Map.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
/*
* Map.js
*
* Uses the react-wrapper to make using google maps js sdk
* easier in react. Beyond basic loading doesn't pretend to
* act like a normal react component.
*/
// src/Map.js

import { useEffect, useRef, useState } from "react";
import { Wrapper, Status } from "@googlemaps/react-wrapper";
import _ from "lodash";
Expand Down Expand Up @@ -325,33 +320,55 @@ function MyMapComponent(props) {
}, [props.rangeStart, props.rangeEnd]);

useEffect(() => {
// Car location maker
const data = props.selectedRow;
if (!data) return;
_.forEach(dataMakers, (m) => m.setMap(null));
dataMakers = [];
const svgMarker = {
path: "M10.453 14.016l6.563-6.609-1.406-1.406-5.156 5.203-2.063-2.109-1.406 1.406zM12 2.016q2.906 0 4.945 2.039t2.039 4.945q0 1.453-0.727 3.328t-1.758 3.516-2.039 3.070-1.711 2.273l-0.75 0.797q-0.281-0.328-0.75-0.867t-1.688-2.156-2.133-3.141-1.664-3.445-0.75-3.375q0-2.906 2.039-4.945t4.945-2.039z",
fillColor: "blue",
fillOpacity: 0.6,
strokeWeight: 0,
rotation: 0,
scale: 1,
anchor: new google.maps.Point(15, 30),

const markerSymbols = {
background: {
path: google.maps.SymbolPath.CIRCLE,
fillColor: "#FFFFFF",
fillOpacity: 0.7,
scale: 18,
strokeColor: "#FFFFFF",
strokeWeight: 2,
strokeOpacity: 0.3,
},
chevron: {
path: "M -1,1 L 0,-1 L 1,1 L 0,0.5 z",
fillColor: "#4285F4",
fillOpacity: 1,
scale: 10,
strokeColor: "#4285F4",
strokeWeight: 1,
rotation: 0,
},
};

const rawLocation = _.get(data.lastlocation, "rawlocation");
if (rawLocation) {
const status = _.get(data, "response.tripstatus");
const state = _.get(data, "response.vehiclestate");
const locationForLog = new window.google.maps.Marker({
const heading = _.get(data.lastlocation, "heading") || 0;
markerSymbols.chevron.rotation = heading;

const backgroundMarker = new window.google.maps.Marker({
position: { lat: rawLocation.latitude, lng: rawLocation.longitude },
map: map,
icon: svgMarker,
title: "Vehicle state " + state + " Trip Status " + status,
icon: markerSymbols.background,
clickable: false,
zIndex: 9,
});
dataMakers.push(locationForLog);

const chevronMarker = new window.google.maps.Marker({
position: { lat: rawLocation.latitude, lng: rawLocation.longitude },
map: map,
icon: markerSymbols.chevron,
zIndex: 10,
});

dataMakers.push(backgroundMarker, chevronMarker);
}
// TODO: for non-vehicle api calls could attempt to interpolate the location
}, [props.selectedRow]);

for (const toggle of props.toggles) {
Expand Down
43 changes: 28 additions & 15 deletions src/TripLogs.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* TripLogs.js
* src/TripLogs.js
*
* Processes raw logs into 'trip segments'. A trip segment might
* be an individual trip, a contiguous non-trip region, or the route
Expand All @@ -9,6 +9,7 @@ import _ from "lodash";
import Trip from "./Trip";
import HighVelocityJump from "./HighVelocityJump";
import MissingUpdate from "./MissingUpdate";
import { log } from "./Utils";

const maxDistanceForDwell = 20; // meters
const requiredUpdatesForDwell = 12; // aka 2 minute assuming update vehicle request at 10 seconds
Expand Down Expand Up @@ -96,16 +97,20 @@ function adjustFieldFormat(log, origPath, newPath, stringToTrim) {
}

function processRawLogs(rawLogs, solutionType) {
console.log(`Processing ${rawLogs.length} raw logs for ${solutionType}`);
log(`Processing ${rawLogs.length} raw logs for ${solutionType}`);
const origLogs = rawLogs.map(toLowerKeys);
const isReversed =
origLogs.length > 1 &&
new Date(origLogs[0].timestamp) >
new Date(origLogs[origLogs.length - 1].timestamp);
console.log(`Raw logs are ${isReversed ? "reversed" : "chronological"}`);
log(`Raw logs are ${isReversed ? "reversed" : "chronological"}`);

let sortedLogs = isReversed ? _.reverse(origLogs) : origLogs;
let newLogs = [];
let lastKnownLocation = null;
let lastKnownHeading = 0;
const vehiclePath =
solutionType === "LMFS" ? "request.deliveryvehicle" : "request.vehicle";

for (let idx = 0; idx < sortedLogs.length; idx++) {
const origLog = sortedLogs[idx];
Expand Down Expand Up @@ -185,6 +190,18 @@ function processRawLogs(rawLogs, solutionType) {
);
}

// Creating lastlocation for trip rows so that these still show the last known car marker
const currentLocation = _.get(newLog, `${vehiclePath}.lastlocation`);
if (currentLocation?.rawlocation) {
lastKnownLocation = currentLocation.rawlocation;
lastKnownHeading = currentLocation.heading;
} else if (lastKnownLocation) {
_.set(newLog, `${vehiclePath}.lastlocation`, {
rawlocation: lastKnownLocation,
heading: lastKnownHeading,
});
}

newLogs.push(newLog);
}
}
Expand All @@ -195,7 +212,7 @@ function processRawLogs(rawLogs, solutionType) {

class TripLogs {
constructor(rawLogs, solutionType) {
console.log(
log(
`Initializing TripLogs with ${rawLogs.length} raw logs for ${solutionType}`
);
this.initialize(rawLogs, solutionType);
Expand Down Expand Up @@ -250,11 +267,9 @@ class TripLogs {
this.processTripSegments();
this.debouncedGetHighVelocityJumps = _.debounce(
(minDate, maxDate, callback) => {
console.log("debouncedGetHighVelocityJumps executing");
log("debouncedGetHighVelocityJumps executing");
const jumps = this.getHighVelocityJumps(minDate, maxDate);
console.log(
`debouncedGetHighVelocityJumps found ${jumps.length} jumps`
);
log(`debouncedGetHighVelocityJumps found ${jumps.length} jumps`);
callback(jumps);
},
300
Expand Down Expand Up @@ -331,7 +346,7 @@ class TripLogs {
* updates.
*/
getETADeltas(minDate, maxDate) {
console.log(`Getting ETA deltas between ${minDate} and ${maxDate}`);
log(`Getting ETA deltas between ${minDate} and ${maxDate}`);
let prevEntry;
this.etaDeltas = this.getRawLogs_(minDate, maxDate)
.filter(
Expand Down Expand Up @@ -366,9 +381,7 @@ class TripLogs {
* at an unrealistic velocity.
*/
getHighVelocityJumps(minDate, maxDate) {
console.log(
`Getting high velocity jumps between ${minDate} and ${maxDate}`
);
log(`Getting high velocity jumps between ${minDate} and ${maxDate}`);

let prevEntry;
let entries = this.getRawLogs_(minDate, maxDate)
Expand All @@ -384,7 +397,7 @@ class TripLogs {
.compact()
.value();

console.log(`Created ${entries.length} HighVelocityJump instances`);
log(`Created ${entries.length} HighVelocityJump instances`);

const velocityJumps = HighVelocityJump.getSignificantJumps(entries);
console.log(`Found ${velocityJumps.length} high velocity jumps`);
Expand All @@ -410,7 +423,7 @@ class TripLogs {
* description of the very simplistic algo used here.
*/
getDwellLocations(minDate, maxDate) {
console.log(`Getting dwell locations between ${minDate} and ${maxDate}`);
log(`Getting dwell locations between ${minDate} and ${maxDate}`);
const dwellLocations = [];
_.forEach(this.rawLogs, (le) => {
const lastLocation = le.lastlocation;
Expand Down Expand Up @@ -470,7 +483,7 @@ class TripLogs {
}

processTripSegments() {
console.log("Processing trip segments");
log("Processing trip segments");
let curTripId = "this is not a segment";
let curTripData = undefined;
let tripIdx = 0;
Expand Down

0 comments on commit 20cb34a

Please sign in to comment.