Skip to content

Commit

Permalink
Improve isochrones (#213)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrstnbwnkl authored Feb 15, 2024
1 parent 60a0a7d commit ba15789
Show file tree
Hide file tree
Showing 11 changed files with 317 additions and 51 deletions.
46 changes: 25 additions & 21 deletions src/Controls/Isochrones/ContoursInformation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,30 +26,34 @@ class ContoursInformation extends React.Component {
return (
<React.Fragment>
{features ? (
features.map((feature, key) => {
return (
<div className={'flex pb2'} key={key}>
<div
className={'flex'}
style={{
alignSelf: 'center',
flexBasis: '140px',
}}
>
<Icon circular name={'time'} />
<div className={'pr2 f6 b pt1 pb1'}>
{feature.properties.contour + ' minutes'}
features
.filter((feature) => !feature.properties.type)
.map((feature, key) => {
return (
<div className={'flex pb2'} key={key}>
<div
className={'flex'}
style={{
alignSelf: 'center',
flexBasis: '140px',
}}
>
<Icon circular name={'time'} />
<div className={'pr2 f6 b pt1 pb1'}>
{feature.properties.contour + ' minutes'}
</div>
</div>
</div>
<div className={'flex'} style={{ alignSelf: 'center' }}>
<Icon circular name={'move'} />
<div className={'pa1 b f6'}>
{feature.properties.area.toFixed(0) + ' km²'}
<div className={'flex'} style={{ alignSelf: 'center' }}>
<Icon circular name={'move'} />
<div className={'pa1 b f6'}>
{(feature.properties.area > 1
? feature.properties.area.toFixed(0)
: feature.properties.area.toFixed(1)) + ' km²'}
</div>
</div>
</div>
</div>
)
})
)
})
) : (
<div>No isochrones found</div>
)}
Expand Down
170 changes: 166 additions & 4 deletions src/Controls/Isochrones/Waypoints/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ import {
clearIsos,
} from 'actions/isochronesActions'

import {
denoise as denoiseParam,
generalize as generalizeParam,
settingsInit,
} from 'Controls/settings-options'

import { updatePermalink, zoomTo } from 'actions/commonActions'

import { debounce } from 'throttle-debounce'
Expand Down Expand Up @@ -115,6 +121,28 @@ class Waypoints extends Component {
})
}

handleDenoiseChange = (e, { value }) => {
value = isNaN(parseFloat(value)) ? settingsInit.denoise : parseFloat(value)

const denoiseName = 'denoise'

this.handleIsoSliderUpdateSettings({
denoiseName,
value,
})
}

handleGeneralizeChange = (e, { value }) => {
value = isNaN(parseInt(value)) ? settingsInit.generalize : parseInt(value)

const generalizeName = 'generalize'

this.handleIsoSliderUpdateSettings({
generalizeName,
value,
})
}

handleRangeChange = (e, { value }) => {
value = isNaN(parseInt(value)) ? 0 : parseInt(value)
if (value > 120) {
Expand All @@ -132,14 +160,22 @@ class Waypoints extends Component {
this.makeIsochronesRequest()
}

handleIsoSliderUpdateSettings = ({ value, maxRangeName, intervalName }) => {
handleIsoSliderUpdateSettings = ({
value,
maxRangeName,
intervalName,
denoiseName,
generalizeName,
}) => {
const { dispatch } = this.props
// maxRangeName can be undefined if interval is being updated
dispatch(
updateIsoSettings({
maxRangeName,
intervalName,
value: parseInt(value),
denoiseName,
generalizeName,
value: parseFloat(value),
})
)

Expand All @@ -165,8 +201,15 @@ class Waypoints extends Component {
)

render() {
const { isFetching, geocodeResults, userInput, maxRange, interval } =
this.props.isochrones
const {
isFetching,
geocodeResults,
userInput,
maxRange,
interval,
denoise,
generalize,
} = this.props.isochrones
const { activeIndex } = this.state

const controlSettings = {
Expand All @@ -192,6 +235,8 @@ class Waypoints extends Component {
step: 1,
},
},
generalize: generalizeParam,
denoise: denoiseParam,
}

return (
Expand Down Expand Up @@ -378,6 +423,123 @@ class Waypoints extends Component {
/>
</div>
</div>
<div className={'pt3 pl3 pr3'}>
<Form.Group inline>
<Form.Input
width={12}
size="small"
label={
<div className="flex flex-row align-top">
<span className="custom-label">
{controlSettings.denoise.name}
</span>
<Popup
content={controlSettings.denoise.description}
size={'tiny'}
trigger={
<Icon
className="pl2"
color="grey"
name="help circle"
/>
}
/>
</div>
}
value={denoise}
placeholder="Enter Value"
name={controlSettings.denoise.param}
onChange={this.handleDenoiseChange}
/>
</Form.Group>
<div className={'mb2 pa2'}>
<Slider
min={0}
max={1}
step={0.1}
value={denoise}
color="secondary"
aria-label="Default"
valueLabelDisplay="auto"
onChange={(e) => {
const param = controlSettings.denoise.param
this.handleIsoSliderUpdateSettings({
denoiseName: param,
value: e.target.value,
})
}}
onChangeCommitted={() => {
this.makeIsochronesRequest()
}}
/>
</div>
</div>
<div className={'pt3 pl3 pr3'}>
<Form.Group inline>
<Form.Input
width={12}
size="small"
label={
<div className="flex flex-row align-top">
<span className="custom-label">
{controlSettings.generalize.name}
</span>
<Popup
content={controlSettings.generalize.description}
size={'tiny'}
trigger={
<Icon
className="pl2"
color="grey"
name="help circle"
/>
}
/>
</div>
}
value={generalize}
placeholder="Enter Value"
name={controlSettings.generalize.param}
onChange={this.handleGeneralizeChange}
/>
<Popup
content={'Units'}
size={'tiny'}
trigger={
<Label
basic
size={'small'}
style={{
cursor: 'default',
}}
>
{controlSettings.generalize.unit}
</Label>
}
/>
</Form.Group>
<div className={'mb2 pa2'}>
<Slider
min={controlSettings.generalize.settings.min}
max={controlSettings.generalize.settings.max}
step={controlSettings.generalize.settings.step}
value={generalize}
color="secondary"
aria-label="Default"
valueLabelDisplay="auto"
onChange={(e) => {
const param = controlSettings.generalize.param
this.handleIsoSliderUpdateSettings({
generalizeName: param,
value: e.target.value,
})
}}
onChangeCommitted={() => {
this.makeIsochronesRequest()
}}
/>
</div>
</div>
</Form>
</Accordion.Content>
</Accordion>
Expand Down
17 changes: 17 additions & 0 deletions src/Controls/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,23 @@ class MainControl extends React.Component {
})
)
}

if ('denoise' in params) {
dispatch(
updateIsoSettings({
denoiseName: 'denoise',
value: params.denoise,
})
)
}
if ('generalize' in params) {
dispatch(
updateIsoSettings({
generalizeName: 'generalize',
value: params.generalize,
})
)
}
}
})
dispatch(zoomTo(processedCoords))
Expand Down
27 changes: 27 additions & 0 deletions src/Controls/settings-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,31 @@ const useTrails = {
step: 0.1,
},
}
export const denoise = {
name: 'Denoise',
description:
'A floating point value from 0 to 1 (default of 1) which can be used to remove smaller contours. A value of 1 will only return the largest contour for a given time value. A value of 0.5 drops any contours that are less than half the area of the largest contour in the set of contours for that same time value.',
param: 'denoise',
unit: '',
settings: {
min: 0,
max: 1,
step: 0.1,
},
}

export const generalize = {
name: 'Generalize',
description:
'A floating point value in meters used as the tolerance for Douglas-Peucker generalization. Note: Generalization of contours can lead to self-intersections, as well as intersections of adjacent contours.',
param: 'generalize',
unit: 'meters',
settings: {
min: 0,
max: 1000,
step: 1,
},
}

export const settingsInit = {
maneuver_penalty: 5,
Expand Down Expand Up @@ -701,6 +726,8 @@ export const settingsInit = {
transit_transfer_max_distance: 800,
disable_hierarchy_pruning: false,
use_trails: 0,
denoise: 0.1,
generalize: 0,
}

export const settingsInitTruckOverride = {
Expand Down
6 changes: 5 additions & 1 deletion src/Controls/settings-panel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class SettingsPanel extends React.Component {
activeIndexGeneral: 0,
generalSettings: {},
extraSettings: {},
isochroneSettings: {},
copied: false,
}
}
Expand All @@ -99,7 +100,7 @@ class SettingsPanel extends React.Component {
// we however only want this component to update if the
// settings really change, therefor deep check with ramda
shouldComponentUpdate(nextProps, nextState) {
const { settings, profile, showSettings } = this.props
const { settings, profile, showSettings, activeTab } = this.props

if (!R.equals(settings, nextProps.settings)) {
return true
Expand All @@ -113,6 +114,9 @@ class SettingsPanel extends React.Component {
if (!R.equals(this.state, nextState)) {
return true
}
if (!R.equals(activeTab, nextProps.activeTab)) {
return true
}
return false
}
// we really only want to call the valhalla backend if settings have changed
Expand Down
Loading

0 comments on commit ba15789

Please sign in to comment.