Skip to content

Commit

Permalink
Merge pull request #1194 from NYCPlanning/DH7-measurement-tools
Browse files Browse the repository at this point in the history
Allow Multiple Measurements
  • Loading branch information
dhochbaum-dcp authored May 8, 2024
2 parents 465982e + 9128ce7 commit 5ab733e
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 74 deletions.
171 changes: 116 additions & 55 deletions app/components/map-measurement-tools.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,72 @@
import Component from '@ember/component';
import numeral from 'numeral';
import { action } from '@ember/object';
import { action, computed } from '@ember/object';
import { inject as service } from '@ember/service';
import drawStyles from '../layers/draw-styles';

function formatMeasurements(measurements) {
// metric calculation

let metricUnits = 'm';
let metricFormat = '0,0';
let metricMeasurement;

let standardUnits = 'feet';
let standardFormat = '0,0';
let standardMeasurement;

if (measurements.type === 'line') {
// user is drawing a line
metricMeasurement = measurements.metric;
if (measurements.metric >= 1000) {
// if over 1000 meters, upgrade metric
metricMeasurement = measurements.metric / 1000;
metricUnits = 'km';
metricFormat = '0.00';
}

standardMeasurement = measurements.standard;
if (standardMeasurement >= 5280) {
// if over 5280 feet, upgrade standard
standardMeasurement /= 5280;
standardUnits = 'mi';
standardFormat = '0.00';
}
} else {
// user is drawing a polygon
metricUnits = 'm²';
metricFormat = '0,0';
metricMeasurement = measurements.metric;

standardUnits = 'ft²';
standardFormat = '0,0';
standardMeasurement = measurements.standard;

if (measurements.metric >= 1000000) {
// if over 1,000,000 meters, upgrade metric
metricMeasurement = measurements.metric / 1000000;
metricUnits = 'km²';
metricFormat = '0.00';
}

if (standardMeasurement >= 27878400) {
// if over 27878400 sf, upgrade standard
standardMeasurement /= 27878400;
standardUnits = 'mi²';
standardFormat = '0.00';
}
}

const formattedMeasurements = {
metric: `${numeral(metricMeasurement).format(metricFormat)} ${metricUnits}`,
standard: `${numeral(standardMeasurement).format(
standardFormat
)} ${standardUnits}`,
};

return formattedMeasurements;
}

export default class MapMeasurementToolsComponent extends Component {
@service mainMap;

Expand All @@ -13,6 +76,12 @@ export default class MapMeasurementToolsComponent extends Component {

drawnMeasurements = null;

previousStoredMeasurements = {
type: null,
metric: 0,
standard: 0,
};

measurementMenuOpen = false;

drawToolsOpen = false;
Expand All @@ -23,23 +92,36 @@ export default class MapMeasurementToolsComponent extends Component {

drawDidRender = false;

drawnFeature = {
type: 'Feature',
geometry: null,
};
drawnFeatures = [];

@computed(
'drawnMeasurements.{metric,standard,type}',
'previousStoredMeasurements.{metric,standard}'
)
get shownMeasurements() {
return formatMeasurements({
id: crypto.randomUUID(),
type: this.drawnMeasurements.type,
metric:
this.drawnMeasurements.metric + this.previousStoredMeasurements.metric,
standard:
this.drawnMeasurements.standard +
this.previousStoredMeasurements.standard,
});
}

@action
async startDraw(type) {
gtag('event', 'draw_tool', {
event_category: 'Measurement',
event_action: 'Used measurement tool',
event_action: `Measurement #${this.drawnFeatures.length}`,
});

// GA
this.metrics.trackEvent('MatomoTagManager', {
category: 'Measurement',
action: 'Used measurement tool',
name: 'Measurement',
name: `Measurement #${this.drawnFeatures.length}`,
});

this.set('didStartDraw', true);
Expand All @@ -55,12 +137,8 @@ export default class MapMeasurementToolsComponent extends Component {
this.set('draw', draw);
const drawMode = type === 'line' ? 'draw_line_string' : 'draw_polygon';
const { mainMap } = this;
if (mainMap.get('drawMode')) {
draw.deleteAll();
} else {
if (!mainMap.get('drawMode')) {
mainMap.mapInstance.addControl(draw);
this.set('drawnFeature', null);
this.set('drawnMeasurements', null);
}
mainMap.set('drawMode', drawMode);
draw.changeMode(drawMode);
Expand All @@ -75,18 +153,36 @@ export default class MapMeasurementToolsComponent extends Component {
}

mainMap.set('drawMode', null);
this.set('drawnFeature', null);
this.set('drawnFeatures', []);
this.set('drawnMeasurements', null);
this.set('previousStoredMeasurements', { metric: 0, standard: 0 });
}

@action
handleDrawCreate(e) {
const { draw } = this;
this.set('drawnFeature', e.features[0].geometry);

this.set('drawnFeatures', [
...this.drawnFeatures,
{ ...e.features[0].geometry, id: crypto.randomUUID() },
]);
this.set('previousStoredMeasurements', {
type: this.drawnMeasurements.type,
metric:
this.drawnMeasurements.metric + this.previousStoredMeasurements.metric,
standard:
this.drawnMeasurements.standard +
this.previousStoredMeasurements.standard,
});
setTimeout(() => {
if (!this.mainMap.isDestroyed && !this.mainMap.isDestroying) {
this.mainMap.mapInstance.removeControl(draw);
this.mainMap.set('drawMode', null);
this.set('drawnMeasurements', {
type: this.drawnMeasurements.type,
metric: 0,
standard: 0,
});
}
}, 100);
}
Expand Down Expand Up @@ -123,61 +219,26 @@ async function calculateMeasurements(feature) {
const drawnLength = lineDistance(feature) * 1000; // meters
const drawnArea = area(feature); // square meters

let metricUnits = 'm';
let metricFormat = '0,0';
let featureType;
let metricMeasurement;

let standardUnits = 'feet';
let standardFormat = '0,0';
let standardMeasurement;

if (drawnLength > drawnArea) {
// user is drawing a line
metricMeasurement = drawnLength;
if (drawnLength >= 1000) {
// if over 1000 meters, upgrade metric
metricMeasurement = drawnLength / 1000;
metricUnits = 'km';
metricFormat = '0.00';
}

standardMeasurement = drawnLength * 3.28084;
if (standardMeasurement >= 5280) {
// if over 5280 feet, upgrade standard
standardMeasurement /= 5280;
standardUnits = 'mi';
standardFormat = '0.00';
}
featureType = 'line';
} else {
// user is drawing a polygon
metricUnits = 'm²';
metricFormat = '0,0';
metricMeasurement = drawnArea;

standardUnits = 'ft²';
standardFormat = '0,0';
standardMeasurement = drawnArea * 10.7639;

if (drawnArea >= 1000000) {
// if over 1,000,000 meters, upgrade metric
metricMeasurement = drawnArea / 1000000;
metricUnits = 'km²';
metricFormat = '0.00';
}

if (standardMeasurement >= 27878400) {
// if over 27878400 sf, upgrade standard
standardMeasurement /= 27878400;
standardUnits = 'mi²';
standardFormat = '0.00';
}
featureType = 'polygon';
}

const drawnMeasurements = {
metric: `${numeral(metricMeasurement).format(metricFormat)} ${metricUnits}`,
standard: `${numeral(standardMeasurement).format(
standardFormat
)} ${standardUnits}`,
metric: metricMeasurement,
standard: standardMeasurement,
type: featureType,
};

return drawnMeasurements;
Expand Down
2 changes: 0 additions & 2 deletions app/layers/drawn-feature.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export default {
line: {
id: 'drawn-feature-line',
type: 'line',
source: 'drawn-feature',
paint: {
Expand All @@ -11,7 +10,6 @@ export default {
},
},
fill: {
id: 'drawn-feature-fill',
type: 'fill',
source: 'drawn-feature',
paint: {
Expand Down
32 changes: 18 additions & 14 deletions app/templates/components/main-map.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -68,23 +68,27 @@
@map={{map.instance}}
@draw={{this.draw}} as |measurement|
>
{{#if measurement.feature}}
<MapboxGlSource
@map={{map.instance}}
@sourceId="drawn-feature"
@options={{hash type="geojson" data=measurement.feature}} as |source|
>
<source.layer
@layer={{this.drawnFeatureLayers.line}}
@before="place_other"
/>
{{#if (eq this.mainMap.drawnFeature.type "Polygon")}}
{{#if measurement.features.length}}
{{#each measurement.features as |feature|}}
<MapboxGlSource
@map={{map.instance}}
@sourceId={{feature.id}}
@options={{hash type="geojson" data=feature}} as |source|
>
<source.layer
@layer={{this.drawnFeatureLayers.fill}}
@id="{{source.id}}-line"
@layer={{this.drawnFeatureLayers.line}}
@before="place_other"
/>
{{/if}}
</MapboxGlSource>
{{#if (eq this.mainMap.drawnFeature.type "Polygon")}}
<source.layer
@id="{{source.id}}-fill"
@layer={{this.drawnFeatureLayers.fill}}
@before="place_other"
/>
{{/if}}
</MapboxGlSource>
{{/each}}
{{/if}}
</MapMeasurementTools>
</Mapbox::BasicMap>
Expand Down
6 changes: 3 additions & 3 deletions app/templates/components/map-measurement-tools.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{yield (hash feature=this.drawnFeature)}}
{{yield (hash features=this.drawnFeatures)}}
{{mapbox-gl-on "draw.create" (action "handleDrawCreate") eventSource=this.map}}
{{mapbox-gl-on "draw.render" (action "handleMeasurement") eventSource=this.map}}
{{! Measurement }}
Expand Down Expand Up @@ -61,9 +61,9 @@
<div class="draw-measurement">
<div data-test-measure="value">
{{#if (eq this.measurementUnitType "standard")}}
{{this.drawnMeasurements.standard}}
{{this.shownMeasurements.standard}}
{{else}}
{{this.drawnMeasurements.metric}}
{{this.shownMeasurements.metric}}
{{/if}}
</div>
<span
Expand Down

0 comments on commit 5ab733e

Please sign in to comment.