Skip to content

Commit

Permalink
Add stop search by GPS boundary box
Browse files Browse the repository at this point in the history
  • Loading branch information
Oliv4945 committed Jan 27, 2024
1 parent 27f1e2b commit 570cbce
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 4 deletions.
22 changes: 18 additions & 4 deletions lib/gtfs/stops.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
formatOrderByClause,
formatSelectClause,
formatWhereClause,
formatWhereClauseBoundaryBox,
formatWhereClauses,
} from '../utils.js';
import { stopsToGeoJSON } from '../geojson-utils.js';
Expand Down Expand Up @@ -37,9 +38,10 @@ export function getStops(query = {}, fields = [], orderBy = [], options = {}) {
const tableName = sqlString.escapeId(stops.filenameBase);
const selectClause = formatSelectClause(fields);
let whereClause = '';
let whereClauses = [];
const orderByClause = formatOrderByClause(orderBy);

const stopQuery = omit(query, [
let stopQuery = omit(query, [
'route_id',
'trip_id',
'service_id',
Expand All @@ -54,9 +56,21 @@ export function getStops(query = {}, fields = [], orderBy = [], options = {}) {
'shape_id',
]);

const whereClauses = Object.entries(stopQuery).map(([key, value]) =>
formatWhereClause(key, value)
);
if (options.boundary_side_m === undefined) {
whereClauses = Object.entries(stopQuery).map(([key, value]) =>
formatWhereClause(key, value)
);
} else {
// Search inside a GPS coordinates boundary box
stopQuery = omit(query, [
'stop_lat',
'stop_lon',
]);
whereClauses.push(...Object.entries(stopQuery).map(([key, value]) =>
formatWhereClause(key, value)
));
whereClauses.push(formatWhereClauseBoundaryBox(query.stop_lat, query.stop_lon, options.boundary_side_m))
}

if (Object.values(tripQuery).length > 0) {
whereClauses.push(`stop_id IN (${buildStoptimeSubquery(tripQuery)})`);
Expand Down
32 changes: 32 additions & 0 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,38 @@ export function formatJoinClause(joinObject) {
.join(' ');
}

function degree2radian(angle) {
return angle * Math.PI / 180;
}

function radian2degree(angle) {
return angle / Math.PI * 180;
}

/*
* Search inside GPS coordinates boundary box
* Distance unit: meters
* */
export function formatWhereClauseBoundaryBox(latitudeDegree, longitudeDegree, boxSide) {

const earthRadius = 6371000;
latitudeDegree = parseFloat(latitudeDegree);
longitudeDegree = parseFloat(longitudeDegree);

const latitudeRadian = degree2radian(latitudeDegree);
const radiusFromLatitude = Math.cos(latitudeRadian) * earthRadius;

// boxSide is divided by 2 as user specify the square side size
// but we are centering the coordinates in the middle of this square
const deltaLatitude = radian2degree(boxSide / 2 / earthRadius);
const deltaLongitude = radian2degree(boxSide / 2 / radiusFromLatitude);

let query = `stop_lat BETWEEN ${latitudeDegree - deltaLatitude} AND ${latitudeDegree + deltaLatitude}`;
query += ` AND stop_lon BETWEEN ${longitudeDegree - deltaLongitude} AND ${longitudeDegree + deltaLongitude}`;

return query;
}

export function formatWhereClause(key, value) {
if (Array.isArray(value)) {
let whereClause = `${sqlString.escapeId(key)} IN (${value
Expand Down
69 changes: 69 additions & 0 deletions test/mocha/get-stops.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,4 +266,73 @@ describe('getStops():', () => {
);
}
});

it('should return array of stops for specific GPS boundaries', () => {
const distance = 100;
const stopLatitude = 37.709538;
const stopLongitude = -122.401586;

const results = getStops({
stop_lat: stopLatitude,
stop_lon: stopLongitude,
},
[], [], { "boundary_side_m": distance }
);

const expectedResult = [
{
stop_id: 'ctba',
stop_code: null,
stop_name: 'Bayshore Caltrain',
tts_stop_name: null,
stop_desc: null,
stop_lat: 37.709544,
stop_lon: -122.401318,
zone_id: null,
stop_url: 'http://www.caltrain.com/stations/bayshorestation.html',
location_type: 1,
parent_station: null,
stop_timezone: null,
wheelchair_boarding: 1,
level_id: null,
platform_code: null
}, {
stop_id: '70032',
stop_code: '70032',
stop_name: 'Bayshore Caltrain',
tts_stop_name: null,
stop_desc: null,
stop_lat: 37.709544,
stop_lon: -122.40198,
zone_id: '1',
stop_url: 'http://www.caltrain.com/stations/bayshorestation.html',
location_type: 0,
parent_station: 'ctba',
stop_timezone: null,
wheelchair_boarding: 1,
level_id: null,
platform_code: 'SB'
}, {
stop_id: '70031',
stop_code: '70031',
stop_name: 'Bayshore Caltrain',
tts_stop_name: null,
stop_desc: null,
stop_lat: 37.709537,
stop_lon: -122.401586,
zone_id: '1',
stop_url: 'http://www.caltrain.com/stations/bayshorestation.html',
location_type: 0,
parent_station: 'ctba',
stop_timezone: null,
wheelchair_boarding: 1,
level_id: null,
platform_code: 'NB'
}
];

should.exist(results);
results.length.should.equal(3);
results.should.match(expectedResult);
});
});

0 comments on commit 570cbce

Please sign in to comment.