From b949c38c3aaecf367b9ff3ca66649b180acb08dc Mon Sep 17 00:00:00 2001 From: Nate-Wessel Date: Tue, 26 Mar 2024 15:43:54 +0000 Subject: [PATCH 1/6] calculate rough compass bearing --- frontend/src/corridor.js | 26 +++++++++++++++++++++++--- frontend/src/intersection.js | 4 +++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/frontend/src/corridor.js b/frontend/src/corridor.js index 8643b9e..7810864 100644 --- a/frontend/src/corridor.js +++ b/frontend/src/corridor.js @@ -69,13 +69,29 @@ export class Corridor extends Factor { } return '' } + get bearing(){ + if( ! this.#intersections.length == 2) return + const [A, B] = this.#intersections + const x = Math.cos(d2r(A.lat)) * Math.sin(d2r(B.lat)) + - Math.sin(d2r(A.lat)) * Math.cos(d2r(B.lat)) * Math.cos(d2r(B.lng - A.lng)) + const y = Math.sin(d2r(B.lng - A.lng)) * Math.cos(d2r(B.lat)) + // degrees from true East, "corrected" 17d for the city's grid rotation + const azimuth = r2d(Math.atan2(x,y)) + const compass = { NE: 45, SE: -45, SW: -135, NW: 135 } + console.log(azimuth) + if( azimuth < compass.NE && azimuth > compass.SE ) return 'East' + if( azimuth > compass.NE && azimuth < compass.NW ) return 'North' + if( azimuth < compass.SE && azimuth > compass.SW ) return 'South' + if( azimuth > compass.NW || azimuth < compass.SW ) return 'West' + return azimuth + } get name(){ if(this.#intersections.length == 1){ return `Incomplete corridor starting from ${this.startCrossStreetsString}` }else if(this.#intersections.length == 2 && this.viaStreets.size > 0){ - return `${this.viaStreetsString} from ${this.startCrossStreetsString} to ${this.endCrossStreetsString}` + return `${this.viaStreetsString} from ${this.startCrossStreetsString} to ${this.endCrossStreetsString} (${this.bearing})` }else if(this.#intersections.length == 2){ // but no via streets (yet?) - return `from ${this.startCrossStreetsString} to ${this.endCrossStreetsString}` + return `from ${this.startCrossStreetsString} to ${this.endCrossStreetsString} (${this.bearing})` } return 'New Corridor' } @@ -111,4 +127,8 @@ function difference(setA, setB) { setDiff.delete(elem) } return setDiff -} \ No newline at end of file +} + +// convert between degrees and radians +function d2r(degrees) { return degrees * (Math.PI / 180) } +function r2d(rad) { return rad / (Math.PI / 180) } \ No newline at end of file diff --git a/frontend/src/intersection.js b/frontend/src/intersection.js index c324f1d..be058a5 100644 --- a/frontend/src/intersection.js +++ b/frontend/src/intersection.js @@ -10,7 +10,9 @@ export class Intersection { this.#streetNames = new Set(streetNames) } get id(){ return this.#id } - get latlng(){ return { lat: this.#lat, lng: this.#lng } } + get lat(){ return this.#lat } + get lng(){ return this.#lng } + get latlng(){ return { lat: this.lat, lng: this.lng } } get displayCoords(){ // for display purposes only return `${this.#lng.toFixed(5)}, ${this.#lat.toFixed(5)}` From e037735610a284675683d020b12432ef9c5711e0 Mon Sep 17 00:00:00 2001 From: Nate-Wessel Date: Tue, 26 Mar 2024 19:19:16 +0000 Subject: [PATCH 2/6] minor cleanup --- frontend/src/corridor.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/corridor.js b/frontend/src/corridor.js index 7810864..48f4f64 100644 --- a/frontend/src/corridor.js +++ b/frontend/src/corridor.js @@ -70,7 +70,7 @@ export class Corridor extends Factor { return '' } get bearing(){ - if( ! this.#intersections.length == 2) return + if( ! this.#intersections.length == 2 ) return undefined; const [A, B] = this.#intersections const x = Math.cos(d2r(A.lat)) * Math.sin(d2r(B.lat)) - Math.sin(d2r(A.lat)) * Math.cos(d2r(B.lat)) * Math.cos(d2r(B.lng - A.lng)) @@ -78,7 +78,6 @@ export class Corridor extends Factor { // degrees from true East, "corrected" 17d for the city's grid rotation const azimuth = r2d(Math.atan2(x,y)) const compass = { NE: 45, SE: -45, SW: -135, NW: 135 } - console.log(azimuth) if( azimuth < compass.NE && azimuth > compass.SE ) return 'East' if( azimuth > compass.NE && azimuth < compass.NW ) return 'North' if( azimuth < compass.SE && azimuth > compass.SW ) return 'South' From db318f3bcd025c23a2f420202beb4d6674eb6ec4 Mon Sep 17 00:00:00 2001 From: Nate-Wessel Date: Tue, 26 Mar 2024 19:24:48 +0000 Subject: [PATCH 3/6] add bearing to output --- frontend/src/corridor.js | 4 +++- frontend/src/travelTimeQuery.js | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/corridor.js b/frontend/src/corridor.js index 48f4f64..6a89e44 100644 --- a/frontend/src/corridor.js +++ b/frontend/src/corridor.js @@ -70,12 +70,14 @@ export class Corridor extends Factor { return '' } get bearing(){ + // azimuth calculation borrowed from: + // http://www.movable-type.co.uk/scripts/latlong.html if( ! this.#intersections.length == 2 ) return undefined; const [A, B] = this.#intersections const x = Math.cos(d2r(A.lat)) * Math.sin(d2r(B.lat)) - Math.sin(d2r(A.lat)) * Math.cos(d2r(B.lat)) * Math.cos(d2r(B.lng - A.lng)) const y = Math.sin(d2r(B.lng - A.lng)) * Math.cos(d2r(B.lat)) - // degrees from true East, "corrected" 17d for the city's grid rotation + // degrees from true East TODO: adjust this by 17 degrees const azimuth = r2d(Math.atan2(x,y)) const compass = { NE: 45, SE: -45, SW: -135, NW: 135 } if( azimuth < compass.NE && azimuth > compass.SE ) return 'East' diff --git a/frontend/src/travelTimeQuery.js b/frontend/src/travelTimeQuery.js index 11de9d0..2c70ee4 100644 --- a/frontend/src/travelTimeQuery.js +++ b/frontend/src/travelTimeQuery.js @@ -57,6 +57,7 @@ export class TravelTimeQuery { const record = new Map() record.set('URI',this.URI) record.set('routeStreets',this.corridor.viaStreetsString) + record.set('bearing',this.corridor.bearing) record.set('startCrossStreets',this.corridor.startCrossStreetsString) record.set('endCrossStreets',this.corridor.endCrossStreetsString) record.set('timeRange',this.timeRange.name) From 6a22a4f324ecc4c0e4f7aa4a41cae68689c8cc19 Mon Sep 17 00:00:00 2001 From: Nate-Wessel Date: Thu, 11 Apr 2024 16:44:41 +0000 Subject: [PATCH 4/6] rename output field, change directions to -bound --- frontend/src/corridor.js | 8 ++++---- frontend/src/travelTimeQuery.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/corridor.js b/frontend/src/corridor.js index 6a89e44..8233b8b 100644 --- a/frontend/src/corridor.js +++ b/frontend/src/corridor.js @@ -80,10 +80,10 @@ export class Corridor extends Factor { // degrees from true East TODO: adjust this by 17 degrees const azimuth = r2d(Math.atan2(x,y)) const compass = { NE: 45, SE: -45, SW: -135, NW: 135 } - if( azimuth < compass.NE && azimuth > compass.SE ) return 'East' - if( azimuth > compass.NE && azimuth < compass.NW ) return 'North' - if( azimuth < compass.SE && azimuth > compass.SW ) return 'South' - if( azimuth > compass.NW || azimuth < compass.SW ) return 'West' + if( azimuth < compass.NE && azimuth > compass.SE ) return 'Eastbound' + if( azimuth > compass.NE && azimuth < compass.NW ) return 'Northbound' + if( azimuth < compass.SE && azimuth > compass.SW ) return 'Southbound' + if( azimuth > compass.NW || azimuth < compass.SW ) return 'Westbound' return azimuth } get name(){ diff --git a/frontend/src/travelTimeQuery.js b/frontend/src/travelTimeQuery.js index 2c70ee4..e504a48 100644 --- a/frontend/src/travelTimeQuery.js +++ b/frontend/src/travelTimeQuery.js @@ -57,7 +57,7 @@ export class TravelTimeQuery { const record = new Map() record.set('URI',this.URI) record.set('routeStreets',this.corridor.viaStreetsString) - record.set('bearing',this.corridor.bearing) + record.set('direction',this.corridor.bearing) record.set('startCrossStreets',this.corridor.startCrossStreetsString) record.set('endCrossStreets',this.corridor.endCrossStreetsString) record.set('timeRange',this.timeRange.name) From 37d54b00f7782fe9023fbfb4d6b28226b23253c7 Mon Sep 17 00:00:00 2001 From: Nate-Wessel Date: Thu, 11 Apr 2024 17:00:26 +0000 Subject: [PATCH 5/6] document direction field --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8e616f6..8f391ef 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ The other fields may require some explanation: | Field | Description | |----|----| | `routeStreets` | The name(s) of the streets along the corridor. I.e. the path taken. | +| `direction` | The approximate compass direction of travel for a corridor e.g. "Westbound". | | `startCrossStreets` | The names of any cross-street(s) at the start of the corridor. If the corridor starts mid-block then coordinates of that point will be returned instead. | | `endCrossStreets` | The names of any cross-street(s) at the end of the corridor. If the corridor ends mid-block then coordinates of that point will be returned instead. | | `mean_travel_time_minutes` | The mean travel time in minutes is given as a floating point number rounded to two decimal places. Where insufficient data was available to complete the request, the value will be null, and in cases where the request was impossible a value of -999 will be assigned. (See `hoursInRange` below). | From f7c98d3fad3e278703d22d683c2c314829523dde Mon Sep 17 00:00:00 2001 From: Nate-Wessel Date: Thu, 11 Apr 2024 17:09:39 +0000 Subject: [PATCH 6/6] modify corridor UI description --- frontend/src/corridor.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/corridor.js b/frontend/src/corridor.js index 8233b8b..8cc28f3 100644 --- a/frontend/src/corridor.js +++ b/frontend/src/corridor.js @@ -84,15 +84,15 @@ export class Corridor extends Factor { if( azimuth > compass.NE && azimuth < compass.NW ) return 'Northbound' if( azimuth < compass.SE && azimuth > compass.SW ) return 'Southbound' if( azimuth > compass.NW || azimuth < compass.SW ) return 'Westbound' - return azimuth + return '' } get name(){ if(this.#intersections.length == 1){ return `Incomplete corridor starting from ${this.startCrossStreetsString}` }else if(this.#intersections.length == 2 && this.viaStreets.size > 0){ - return `${this.viaStreetsString} from ${this.startCrossStreetsString} to ${this.endCrossStreetsString} (${this.bearing})` + return `${this.viaStreetsString} ${this.bearing.toLowerCase()} from ${this.startCrossStreetsString} to ${this.endCrossStreetsString}` }else if(this.#intersections.length == 2){ // but no via streets (yet?) - return `from ${this.startCrossStreetsString} to ${this.endCrossStreetsString} (${this.bearing})` + return `${this.bearing.toLowerCase()} from ${this.startCrossStreetsString} to ${this.endCrossStreetsString}` } return 'New Corridor' }