Skip to content

Commit

Permalink
fill in PT leg in elevation graph
Browse files Browse the repository at this point in the history
  • Loading branch information
abhumbla committed Oct 5, 2023
1 parent f383c55 commit 3e36fd9
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 25 deletions.
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"bowser": "^2.11.0",
"browserslist": "^4.18.1",
"chart.js": "^4.4.0",
"chartjs-plugin-annotation": "^3.0.1",
"classnames": "^2.3.1",
"color": "^4.2.1",
"eslint": "^8.3.0",
Expand Down
125 changes: 100 additions & 25 deletions src/components/ItineraryElevationProfile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,137 @@ import './ItineraryElevationProfile.css';

import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Filler,
Legend,
} from 'chart.js';
import AnnotationPlugin from 'chartjs-plugin-annotation';
import { Scatter } from 'react-chartjs-2';

import distance from '@turf/distance';
import * as turf from '@turf/helpers';

ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Filler,
Legend,
AnnotationPlugin,
);

export default function ItineraryElevationProfile(props) {
const { route } = props;

const points = [];
const ptLegs = [];
let ptLegWithoutHeight = [];
let currentDist = 0;
let currentPoint = route.legs[0].geometry.coordinates[0];
let maxHeight = 0;
for (const leg of route.legs) {
for (const point of leg.geometry.coordinates) {
const dist = distance(turf.point(currentPoint), turf.point(point));
let currPTLeg = { data: [] };
console.log(route);
for (let i = 0; i < route.legs.length; i++) {
const leg = route.legs[i];
for (let j = 0; j < leg.geometry.coordinates.length; j++) {
const point = leg.geometry.coordinates[j];
const dist = distance(turf.point(currentPoint), turf.point(point), {
units: 'miles',
});
currentDist += dist;
currentPoint = point;
if (point.length === 3) {
points.push({ x: currentDist, y: currentPoint[2] });
if (currentPoint[2] > maxHeight) {
maxHeight = currentPoint[2];
const pointHeight = currentPoint[2] / 0.3048;
points.push({ x: currentDist, y: pointHeight });
if (pointHeight > maxHeight) {
maxHeight = pointHeight;
}
if (
j === leg.geometry.coordinates.length - 1 &&
i < route.legs.length - 1 &&
route.legs[i + 1].type === 'pt'
) {
currPTLeg.data.push({
x: currentDist,
y: pointHeight,
type: 'start',
});
}
if (j === 0 && i > 0 && route.legs[i - 1].type === 'pt') {
currPTLeg.data.push({ x: currentDist, y: pointHeight, type: 'end' });
ptLegs.push(currPTLeg);
currPTLeg = { data: [] };
// Check if we have any transit legs without a start/end height
if (ptLegWithoutHeight.length) {
const startHeight = ptLegs[ptLegWithoutHeight[0]].data[0].y;
const heightDiff = pointHeight - startHeight;
for (let k = 0; k < ptLegWithoutHeight.length; k++) {
const frac = (k + 1) / (ptLegWithoutHeight.length + 1);
ptLegs[ptLegWithoutHeight[k]].data[1].y =
startHeight + frac * heightDiff;
ptLegs[ptLegWithoutHeight[k] + 1].data[0].y =
startHeight + frac * heightDiff;
}
ptLegWithoutHeight = [];
}
}
} else {
// Sometimes two transit legs are next to each other without a bike leg in between
if (
j === leg.geometry.coordinates.length - 1 &&
i < route.legs.length - 1 &&
route.legs[i + 1].type === 'pt'
) {
currPTLeg.data.push({ x: currentDist, y: null, type: 'end' });
ptLegs.push(currPTLeg);
currPTLeg = { data: [] };
ptLegWithoutHeight.push(ptLegs.length - 1);
}
if (j === 0 && i > 0 && route.legs[i - 1].type === 'pt') {
currPTLeg.data.push({ x: currentDist, y: null, type: 'start' });
}
points.push({ x: currentDist, y: null });
}
if (j === 0 && leg.type === 'pt') {
currPTLeg['backgroundColor'] = leg.route_color;
currPTLeg['label'] = leg.route_name;
currPTLeg['name'] = leg.trip_id;
currPTLeg['showLine'] = true;
currPTLeg['fill'] = true;
}
}
}

console.log(points);
const annotations = {};
const datasets = [
{
fill: true,
label: 'Elevation',
data: points,
borderColor: 'rgb(53, 162, 235)',
backgroundColor: 'rgba(53, 162, 235, 0.5)',
showLine: true,
},
];
for (const ptLeg of ptLegs) {
annotations[ptLeg.name] = {
type: 'label',
content: ptLeg.label,
xValue: (ptLeg.data[0].x + ptLeg.data[1].x) / 2,
yValue: (ptLeg.data[0].y + ptLeg.data[1].y) / 2,
backgroundColor: 'rgba(245,245,245)',
};
datasets.push(ptLeg);
}

const options = {
elements: {
point: {
radius: 0,
},
},
scales: {
x: {
min: 0,
Expand All @@ -65,34 +145,29 @@ export default function ItineraryElevationProfile(props) {
},
y: {
min: 0,
max: maxHeight + 2,
max: maxHeight + 5,
ticks: {
stepSize: 10,
},
},
},
plugins: {
tooltip: {
enabled: false,
},
legend: {
position: 'top',
display: false,
},
title: {
display: true,
text: 'Elevation',
},
annotation: { annotations },
},
};

const data = {
datasets: [
{
fill: true,
label: 'Elevation',
data: points,
borderColor: 'rgb(53, 162, 235)',
backgroundColor: 'rgba(53, 162, 235, 0.5)',
showLine: true,
},
],
datasets,
};

return <Scatter options={options} data={data} />;
Expand Down

0 comments on commit 3e36fd9

Please sign in to comment.