diff --git a/web/client/components/map/leaflet/MeasurementSupport.jsx b/web/client/components/map/leaflet/MeasurementSupport.jsx
index ab836f9a8d..27bf7a469b 100644
--- a/web/client/components/map/leaflet/MeasurementSupport.jsx
+++ b/web/client/components/map/leaflet/MeasurementSupport.jsx
@@ -2,10 +2,144 @@ const PropTypes = require('prop-types');
 const React = require('react');
 const assign = require('object-assign');
 var L = require('leaflet');
-const {slice} = require('lodash');
-const {reproject, calculateAzimuth, calculateDistance, transformLineToArcs} = require('../../../utils/CoordinatesUtils');
+const {
+    slice
+} = require('lodash');
+const {
+    reproject,
+    calculateAzimuth,
+    calculateDistance,
+    transformLineToArcs
+} = require('../../../utils/CoordinatesUtils');
+const {
+    convertUom,
+    getFormattedBearingValue
+} = require('../../../utils/MeasureUtils');
 require('leaflet-draw');
 
+let defaultPrecision = {
+    km: 2,
+    ha: 2,
+    m: 2,
+    mi: 2,
+    ac: 2,
+    yd: 0,
+    ft: 0,
+    nm: 2,
+    sqkm: 2,
+    sqha: 2,
+    sqm: 2,
+    sqmi: 2,
+    sqac: 2,
+    sqyd: 2,
+    sqft: 2,
+    sqnm: 2
+};
+
+
+L.getMeasureWithTreshold = (value, threshold, source, dest, precision, sourceLabel, destLabel) => {
+    if (value > threshold) {
+        return L.GeometryUtil.formattedNumber(convertUom(value, source, dest), precision[dest]) + ' ' + destLabel;
+    }
+    return L.GeometryUtil.formattedNumber(value, precision[source]) + ' ' + sourceLabel;
+};
+
+/** @method readableDistance(distance, units): string
+ * Converts a metric distance to one of [ feet, nauticalMile, metric or yards ] string
+ *
+ * @alternative
+ * @method readableDistance(distance, isMetric, useFeet, isNauticalMile, precision, options): string
+ * Converts metric distance to distance string.
+ * The value will be rounded as defined by the precision option object.
+ * this override is necesary due to the customization on how the measure label is presented and for adding bearing support
+*/
+
+L.GeometryUtil.readableDistance = (distance, isMetric, isFeet, isNauticalMile, precision, options) => {
+    if (options.geomType === 'Bearing') {
+        return options.bearing;
+    }
+    let p = L.Util.extend({}, defaultPrecision, precision);
+    const {unit, label} = options.uom.length;
+
+    let distanceStr = L.GeometryUtil.formattedNumber(convertUom(distance, "m", unit), p[unit]) + ' ' + label;
+    if (options.useTreshold) {
+        if (isMetric) {
+            distanceStr = L.getMeasureWithTreshold(distance, 1000, "m", "km", p, "m", "km");
+        }
+        if (unit === "mi") {
+            distanceStr = L.getMeasureWithTreshold(convertUom(distance, "m", "yd"), 1760, "yd", "mi", p, "yd", "mi");
+        }
+    }
+    return distanceStr;
+};
+
+/** @method readableArea(area, isMetric, precision): string
+ * @return a readable area string in yards or metric.
+ * The value will be rounded as defined by the precision option object.
+ * this override is necesary due to the customization on how the area measure label is presented
+ supporting also the square nautical miles and square feets
+ */
+L.GeometryUtil.readableArea = (area, isMetric, precision, options) => {
+    const {unit, label} = options.uom.area;
+    let p = L.Util.extend({}, defaultPrecision, precision);
+    let areaStr = L.GeometryUtil.formattedNumber(convertUom(area, "sqm", unit), p[unit]) + ' ' + label;
+    if (options.useTreshold) { // this is done for retrocompatibility
+        if (isMetric) {
+            areaStr = L.getMeasureWithTreshold(area, 1000000, "sqm", "sqkm", p, "m²", "km²");
+        }
+        if (unit === "sqmi") {
+            areaStr = L.getMeasureWithTreshold(convertUom(area, "sqm", "sqyd"), 3097600, "sqyd", "sqmi", p, "yd²", "mi²");
+        }
+    }
+    return areaStr;
+};
+
+/**
+ * this is need to pass custom options as uom, useTreshold to the readableArea function
+*/
+L.Draw.Polygon.prototype._getMeasurementString = function() {
+    let area = this._area;
+    let measurementString = '';
+    if (!area && !this.options.showLength) {
+        return null;
+    }
+    if (this.options.showLength) {
+        measurementString = L.Draw.Polyline.prototype._getMeasurementString.call(this);
+    }
+
+    if (area) {
+        // here is the custom option passed to geom util func
+        const opt = {
+            uom: this.options.uom,
+            useTreshold: this.options.useTreshold
+        };
+        measurementString += this.options.showLength ? '<br>' : '' + L.GeometryUtil.readableArea(area, this.options.metric, this.options.precision, opt);
+    }
+    return measurementString;
+};
+/**
+ * this is need to pass custom options as uom, useTreshold, bearing to the readableDistance function
+*/
+L.Draw.Polyline.prototype._getMeasurementString = function() {
+    let currentLatLng = this._currentLatLng;
+    let previousLatLng = this._markers[this._markers.length - 1].getLatLng();
+    let distance;
+
+    // Calculate the distance from the last fixed point to the mouse position based on the version
+    if (L.GeometryUtil.isVersion07x()) {
+        distance = previousLatLng && currentLatLng && currentLatLng.distanceTo ? this._measurementRunningTotal + currentLatLng.distanceTo(previousLatLng) * (this.options.factor || 1) : this._measurementRunningTotal || 0;
+    } else {
+        distance = previousLatLng && currentLatLng ? this._measurementRunningTotal + this._map.distance(currentLatLng, previousLatLng) * (this.options.factor || 1) : this._measurementRunningTotal || 0;
+    }
+    // here is the custom option passed to geom util func
+    const opt = {
+        uom: this.options.uom,
+        useTreshold: this.options.useTreshold,
+        geomType: this.options.geomType,
+        bearing: this.options.bearing ? getFormattedBearingValue(this.options.bearing) : 0
+    };
+    return L.GeometryUtil.readableDistance(distance, this.options.metric, this.options.feet, this.options.nautic, this.options.precision, opt);
+};
 class MeasurementSupport extends React.Component {
     static displayName = 'MeasurementSupport';
 
@@ -13,10 +147,13 @@ class MeasurementSupport extends React.Component {
         map: PropTypes.object,
         metric: PropTypes.bool,
         feet: PropTypes.bool,
+        nautic: PropTypes.bool,
+        useTreshold: PropTypes.bool,
         projection: PropTypes.string,
         measurement: PropTypes.object,
         changeMeasurementState: PropTypes.func,
         messages: PropTypes.object,
+        uom: PropTypes.object,
         updateOnMouseMove: PropTypes.bool
     };
 
@@ -25,20 +162,34 @@ class MeasurementSupport extends React.Component {
     };
 
     static defaultProps = {
+        uom: {
+            length: {unit: 'm', label: 'm'},
+            area: {unit: 'sqm', label: 'm²'}
+        },
         updateOnMouseMove: false,
         metric: true,
+        nautic: false,
+        useTreshold: false,
         feet: false
     };
 
+
     componentWillReceiveProps(newProps) {
-        if (newProps.measurement.geomType && newProps.measurement.geomType !== this.props.measurement.geomType ) {
+        if ((newProps && newProps.uom && newProps.uom.length && newProps.uom.length.unit) !== (this.props && this.props.uom && this.props.uom.length && this.props.uom.length.unit) && this.drawControl) {
+            const uomOptions = this.uomLengthOptions(newProps);
+            this.drawControl.setOptions({...uomOptions, uom: newProps.uom});
+        }
+        if ((newProps && newProps.uom && newProps.uom.area && newProps.uom.area.unit) !== (this.props && this.props.uom && this.props.uom.area && this.props.uom.area.unit) && this.drawControl) {
+            const uomOptions = this.uomAreaOptions(newProps);
+            this.drawControl.setOptions({...uomOptions, uom: newProps.uom});
+        }
+        if (newProps.measurement.geomType && newProps.measurement.geomType !== this.props.measurement.geomType) {
             this.addDrawInteraction(newProps);
         }
         if (!newProps.measurement.geomType) {
             this.removeDrawInteraction();
         }
     }
-
     onDrawStart = () => {
         this.removeArcLayer();
         this.drawing = true;
@@ -54,11 +205,20 @@ class MeasurementSupport extends React.Component {
         let feature = this.lastLayer && this.lastLayer.toGeoJSON() || {};
         if (this.props.measurement.geomType === 'Point') {
             let pos = this.drawControl._marker.getLatLng();
-            let point = {x: pos.lng, y: pos.lat, srs: 'EPSG:4326'};
-            let newMeasureState = assign({}, this.props.measurement, {point: point, feature});
+            let point = {
+                x: pos.lng,
+                y: pos.lat,
+                srs: 'EPSG:4326'
+            };
+            let newMeasureState = assign({}, this.props.measurement, {
+                point: point,
+                feature
+            });
             this.props.changeMeasurementState(newMeasureState);
         } else {
-            let newMeasureState = assign({}, this.props.measurement, {feature});
+            let newMeasureState = assign({}, this.props.measurement, {
+                feature
+            });
             this.props.changeMeasurementState(newMeasureState);
         }
         if (this.props.measurement.lineMeasureEnabled && this.lastLayer) {
@@ -114,7 +274,7 @@ class MeasurementSupport extends React.Component {
         if (this.props.measurement.geomType === 'LineString' && this.drawControl._markers && this.drawControl._markers.length > 1) {
             // calculate length
             const reprojectedCoords = this.drawControl._markers.reduce((p, c) => {
-                const {lng, lat} = c.getLatLng();
+                const { lng, lat } = c.getLatLng();
                 return [...p, [lng, lat]];
             }, []);
 
@@ -126,29 +286,15 @@ class MeasurementSupport extends React.Component {
             area = L.GeometryUtil.geodesicArea(latLngs);
         } else if (this.props.measurement.geomType === 'Bearing' && this.drawControl._markers && this.drawControl._markers.length > 0) {
             // calculate bearing
-            let bearingMarkers = this.drawControl._markers;
-            let coords1 = [bearingMarkers[0].getLatLng().lng, bearingMarkers[0].getLatLng().lat];
-            let coords2;
-            if (bearingMarkers.length === 1) {
-                coords2 = [currentLatLng.lng, currentLatLng.lat];
-            } else if (bearingMarkers.length === 2) {
-                coords2 = [bearingMarkers[1].getLatLng().lng, bearingMarkers[1].getLatLng().lat];
-            }
-            // in order to align the results between leaflet and openlayers the coords are repojected only for leaflet
-            coords1 = reproject(coords1, 'EPSG:4326', this.props.projection);
-            coords2 = reproject(coords2, 'EPSG:4326', this.props.projection);
-            // calculate the azimuth as base for bearing information
-            bearing = calculateAzimuth(coords1, coords2, this.props.projection);
+            bearing = this.calculateBearing();
         }
         // let drawn geom stay on the map
-        let newMeasureState = assign({}, this.props.measurement,
-            {
-                point: null, // Point is set in onDraw.created
-                len: distance,
-                area: area,
-                bearing: bearing
-            }
-        );
+        let newMeasureState = assign({}, this.props.measurement, {
+            point: null, // Point is set in onDraw.created
+            len: distance,
+            area: area,
+            bearing: bearing
+        });
         this.props.changeMeasurementState(newMeasureState);
     };
 
@@ -182,23 +328,28 @@ class MeasurementSupport extends React.Component {
         this.props.map.on('draw:created', this.onDrawCreated, this);
         this.props.map.on('draw:drawstart', this.onDrawStart, this);
         this.props.map.on('click', this.mapClickHandler, this);
+        this.props.map.on('mousemove', this.updateBearing, this);
+
         if (this.props.updateOnMouseMove) {
             this.props.map.on('mousemove', this.updateMeasurementResults, this);
         }
-
         if (newProps.measurement.geomType === 'Point') {
             this.drawControl = new L.Draw.Marker(this.props.map, {
                 repeatMode: false
             });
         } else if (newProps.measurement.geomType === 'LineString' ||
-                newProps.measurement.geomType === 'Bearing') {
+            newProps.measurement.geomType === 'Bearing') {
+            const uomOptions = this.uomLengthOptions(newProps);
             this.drawControl = new L.Draw.Polyline(this.props.map, {
                 shapeOptions: {
                     color: '#ffcc33',
                     weight: 2
                 },
-                metric: this.props.metric,
-                feet: this.props.feet,
+                showLength: true,
+                useTreshold: newProps.useTreshold,
+                uom: newProps.uom,
+                geomType: newProps.measurement.geomType,
+                ...uomOptions,
                 repeatMode: false,
                 icon: new L.DivIcon({
                     iconSize: new L.Point(8, 8),
@@ -210,13 +361,21 @@ class MeasurementSupport extends React.Component {
                 })
             });
         } else if (newProps.measurement.geomType === 'Polygon') {
+            const uomOptions = this.uomAreaOptions(newProps);
             this.drawControl = new L.Draw.Polygon(this.props.map, {
                 shapeOptions: {
                     color: '#ffcc33',
                     weight: 2,
                     fill: 'rgba(255, 255, 255, 0.2)'
                 },
+                showArea: true,
+                allowIntersection: false,
+                showLength: false,
                 repeatMode: false,
+                useTreshold: newProps.useTreshold,
+                uom: newProps.uom,
+                geomType: newProps.measurement.geomType,
+                ...uomOptions,
                 icon: new L.DivIcon({
                     iconSize: new L.Point(8, 8),
                     className: 'leaflet-div-icon leaflet-editing-icon'
@@ -239,6 +398,7 @@ class MeasurementSupport extends React.Component {
             this.removeLastLayer();
             this.props.map.off('draw:created', this.onDrawCreated, this);
             this.props.map.off('draw:drawstart', this.onDrawStart, this);
+            this.props.map.off('mousemove', this.updateBearing, this);
             this.props.map.off('click', this.mapClickHandler, this);
             if (this.props.updateOnMouseMove) {
                 this.props.map.off('mousemove', this.updateMeasurementResults, this);
@@ -255,6 +415,57 @@ class MeasurementSupport extends React.Component {
             this.props.map.removeLayer(this.arcLayer);
         }
     }
+
+    uomLengthOptions = (props) => {
+        let {
+            unit
+        } = props.uom.length;
+        const metric = unit === "m" || unit === "km"; // false = miles&yards
+        const nautic = unit === "nm";
+        const feet = unit === "ft";
+        return {
+            metric,
+            nautic,
+            feet
+        };
+    }
+    uomAreaOptions = (props) => {
+        let {
+            unit
+        } = props.uom.area;
+        const metric = unit === "sqm" || unit === "sqkm"; // false = miles
+        const nautic = unit === "sqnm";
+        const feet = unit === "sqft";
+        return {
+            metric,
+            nautic,
+            feet
+        };
+    }
+
+    calculateBearing = () => {
+        let currentLatLng = this.drawControl._currentLatLng;
+        let bearing = 0;
+        let bearingMarkers = this.drawControl._markers;
+        let coords1 = [bearingMarkers[0].getLatLng().lng, bearingMarkers[0].getLatLng().lat];
+        let coords2;
+        if (bearingMarkers.length === 1) {
+            coords2 = [currentLatLng.lng, currentLatLng.lat];
+        } else if (bearingMarkers.length === 2) {
+            coords2 = [bearingMarkers[1].getLatLng().lng, bearingMarkers[1].getLatLng().lat];
+        }
+        // in order to align the results between leaflet and openlayers the coords are repojected only for leaflet
+        coords1 = reproject(coords1, 'EPSG:4326', this.props.projection);
+        coords2 = reproject(coords2, 'EPSG:4326', this.props.projection);
+        // calculate the azimuth as base for bearing information
+        bearing = calculateAzimuth(coords1, coords2, this.props.projection);
+        return bearing;
+    }
+    updateBearing = () => {
+        if (this.props.measurement.geomType === 'Bearing' && this.drawControl._markers && this.drawControl._markers.length > 0) {
+            this.drawControl.setOptions({ bearing: this.calculateBearing() });
+        }
+    }
 }
 
 module.exports = MeasurementSupport;
diff --git a/web/client/components/map/leaflet/__tests__/MeasurementSupport-test.jsx b/web/client/components/map/leaflet/__tests__/MeasurementSupport-test.jsx
index 60c22fc9d0..a7b8c9d7b3 100644
--- a/web/client/components/map/leaflet/__tests__/MeasurementSupport-test.jsx
+++ b/web/client/components/map/leaflet/__tests__/MeasurementSupport-test.jsx
@@ -11,7 +11,24 @@ var React = require('react');
 var ReactDOM = require('react-dom');
 var L = require('leaflet');
 var MeasurementSupport = require('../MeasurementSupport');
-
+let defaultPrecision = {
+    km: 2,
+    ha: 2,
+    m: 2,
+    mi: 2,
+    ac: 2,
+    yd: 0,
+    ft: 0,
+    nm: 2,
+    sqkm: 2,
+    sqha: 2,
+    sqm: 2,
+    sqmi: 2,
+    sqac: 2,
+    sqyd: 2,
+    sqft: 2,
+    sqnm: 2
+};
 describe('Leaflet MeasurementSupport', () => {
     var msNode;
     function getMapLayersNum(map) {
@@ -286,4 +303,214 @@ describe('Leaflet MeasurementSupport', () => {
         document.getElementById('map').click();
     });
 
+    it('test L.GeometryUtil.readableDistance with Bearing', () => {
+        const distance = 1;
+        const isMetric = true;
+        const isFeet = false;
+        const isNauticalMile = false;
+        const precision = null;
+        const options = {
+            geomType: "Bearing",
+            bearing: "5° N 4° E",
+            useTreshold: true,
+            uom: {
+                length: {
+                    unit: "m",
+                    label: "m"
+                }
+            }
+        };
+        let distanceStr = L.GeometryUtil.readableDistance(distance, isMetric, isFeet, isNauticalMile, precision, options);
+        expect(distanceStr).toBe("5° N 4° E");
+    });
+    it('test L.GeometryUtil.readableDistance length with trehsold', () => {
+        const distance = 1;
+        const isMetric = true;
+        const isFeet = false;
+        const isNauticalMile = false;
+        const precision = null;
+        const options = {
+            geomType: "LineString",
+            bearing: 0,
+            useTreshold: true,
+            uom: {
+                length: {
+                    unit: "km",
+                    label: "km"
+                }
+            }
+        };
+        let distanceStr = L.GeometryUtil.readableDistance(distance, isMetric, isFeet, isNauticalMile, precision, options);
+        expect(distanceStr).toBe("1.00 m");
+
+        distanceStr = L.GeometryUtil.readableDistance(distance * 1E4, isMetric, isFeet, isNauticalMile, precision, options);
+        expect(distanceStr).toBe("10.00 km");
+    });
+    it('test L.GeometryUtil.readableDistance metric length with no trehsold', () => {
+        const distance = 1000;
+        const isMetric = true;
+        const isFeet = false;
+        const isNauticalMile = false;
+        const precision = null;
+        const options = {
+            geomType: "LineString",
+            bearing: 0,
+            useTreshold: false,
+            uom: {
+                length: {
+                    unit: "km",
+                    label: "km"
+                }
+            }
+        };
+        let distanceStr = L.GeometryUtil.readableDistance(distance, isMetric, isFeet, isNauticalMile, precision, options);
+        expect(distanceStr).toBe("1.00 km");
+    });
+    it('test L.GeometryUtil.readableDistance imperial length with trehsold', () => {
+        const distance = 10;
+        const isMetric = false;
+        const isFeet = false;
+        const isNauticalMile = false;
+        const precision = null;
+        const options = {
+            geomType: "LineString",
+            bearing: 0,
+            useTreshold: true,
+            uom: {
+                length: {
+                    unit: "mi",
+                    label: "mi"
+                }
+            }
+        };
+        let distanceStr = L.GeometryUtil.readableDistance(distance, isMetric, isFeet, isNauticalMile, precision, options);
+        expect(distanceStr).toBe("11 yd");
+        distanceStr = L.GeometryUtil.readableDistance(distance * 1e4, isMetric, isFeet, isNauticalMile, precision, options);
+        expect(distanceStr).toBe("62.14 mi");
+    });
+    it('test L.GeometryUtil.readableArea imperial length with trehsold', () => {
+        const area = 100000;
+        const isMetric = false;
+        const precision = null;
+        const options = {
+            geomType: "LineString",
+            bearing: 0,
+            useTreshold: true,
+            uom: {
+                area: {
+                    unit: "sqmi",
+                    label: "mi²"
+                }
+            }
+        };
+        let areaStr = L.GeometryUtil.readableArea(area, isMetric, precision, options);
+        expect(areaStr).toBe("119600.00 yd²");
+        areaStr = L.GeometryUtil.readableArea(area * 1e6, isMetric, precision, options);
+        expect(areaStr).toBe("38610.22 mi²");
+    });
+    it('test L.GeometryUtil.readableArea metric length with trehsold', () => {
+        const area = 100000;
+        const isMetric = true;
+        const precision = null;
+        const options = {
+            geomType: "LineString",
+            bearing: 0,
+            useTreshold: true,
+            uom: {
+                area: {
+                    unit: "sqkm",
+                    label: "km²"
+                }
+            }
+        };
+        let areaStr = L.GeometryUtil.readableArea(area, isMetric, precision, options);
+        expect(areaStr).toBe("100000.00 m²");
+        areaStr = L.GeometryUtil.readableArea(area * 1e6, isMetric, precision, options);
+        expect(areaStr).toBe("100000.00 km²");
+    });
+    it('test L.GeometryUtil.readableArea metric length with no trehsold', () => {
+        const area = 100000;
+        const isMetric = true;
+        const precision = null;
+        const options = {
+            geomType: "LineString",
+            bearing: 0,
+            useTreshold: false,
+            uom: {
+                area: {
+                    unit: "sqkm",
+                    label: "km²"
+                }
+            }
+        };
+        let areaStr = L.GeometryUtil.readableArea(area, isMetric, precision, options);
+        expect(areaStr).toBe("0.10 km²");
+        areaStr = L.GeometryUtil.readableArea(area * 1e3, isMetric, precision, options);
+        expect(areaStr).toBe("100.00 km²");
+    });
+    it('test L.getMeasureWithTreshold', () => {
+        const value = 100000;
+        const threshold = 1000;
+        const precision = defaultPrecision;
+        const source = "m";
+        const dest = "km";
+        const sourceLabel = "m";
+        const destLabel = "km";
+
+        // value > treshold
+        let areaStr = L.getMeasureWithTreshold(value, threshold, source, dest, precision, sourceLabel, destLabel);
+        expect(areaStr).toBe("100.00 km");
+        // value < treshold
+        areaStr = L.getMeasureWithTreshold(value, threshold * 1e3, source, dest, precision, sourceLabel, destLabel);
+        expect(areaStr).toBe("100000.00 m");
+    });
+    it('test L.Draw.Polygon.prototype._getMeasurementString', () => {
+        L.Draw.Polygon.prototype.options = {
+            metric: true,
+            precision: undefined,
+            useTreshold: true,
+            uom: {
+                area: {
+                    unit: "sqkm",
+                    label: "km²"
+                }
+            },
+            showLength: false
+        };
+        L.Draw.Polygon.prototype._area = 1000;
+
+        let areaStr = L.Draw.Polygon.prototype._getMeasurementString();
+        expect(areaStr).toBe("1000.00 m²");
+
+    });
+    it('test L.Draw.Polyline.prototype._getMeasurementString', () => {
+        L.Draw.Polyline.prototype.options = {
+            metric: true,
+            feet: false,
+            nautic: false,
+            precision: undefined,
+            useTreshold: true,
+            uom: {
+                length: {
+                    unit: "km",
+                    label: "km"
+                }
+            },
+            showLength: false
+        };
+        let map = L.map("map", {
+            center: [51.505, -0.09],
+            zoom: 13
+        });
+        L.Draw.Polyline.prototype._map = map;
+        L.Draw.Polyline.prototype._measurementRunningTotal = 0;
+        L.Draw.Polyline.prototype._currentLatLng = L.latLng([50.5, 30.5]);
+        L.Draw.Polyline.prototype._markers = [L.marker([50.5, 30.5]), L.marker([52.5, 30.5])];
+
+        let distanceStr = L.Draw.Polyline.prototype._getMeasurementString();
+        expect(distanceStr).toBe("222.39 km");
+
+    });
+
+
 });
diff --git a/web/client/components/map/openlayers/MeasurementSupport.jsx b/web/client/components/map/openlayers/MeasurementSupport.jsx
index 5a84729767..f23b6a6b88 100644
--- a/web/client/components/map/openlayers/MeasurementSupport.jsx
+++ b/web/client/components/map/openlayers/MeasurementSupport.jsx
@@ -13,7 +13,7 @@ const assign = require('object-assign');
 const ol = require('openlayers');
 const wgs84Sphere = new ol.Sphere(6378137);
 const {reprojectGeoJson, reproject, calculateAzimuth, calculateDistance, transformLineToArcs} = require('../../../utils/CoordinatesUtils');
-const {getFormattedLength, getFormattedArea, getFormattedBearingValue} = require('../../../utils/MeasureUtils');
+const {convertUom, getFormattedBearingValue} = require('../../../utils/MeasureUtils');
 const {getMessageById} = require('../../../utils/LocaleUtils');
 
 class MeasurementSupport extends React.Component {
@@ -345,7 +345,7 @@ class MeasurementSupport extends React.Component {
         const reprojectedCoords = this.reprojectedCoordinates(sketchCoords);
         const length = calculateDistance(reprojectedCoords, this.props.measurement.lengthFormula);
         const {label, unit} = this.props.uom && this.props.uom.length;
-        const output = round(getFormattedLength(unit, length), 2);
+        const output = round(convertUom(length, "m", unit), 2);
         return output + " " + (label);
     };
 
@@ -357,7 +357,7 @@ class MeasurementSupport extends React.Component {
     formatArea = (polygon) => {
         const area = this.calculateGeodesicArea(polygon.getLinearRing(0).getCoordinates());
         const {label, unit} = this.props.uom && this.props.uom.area;
-        const output = round(getFormattedArea(unit, area), 2);
+        const output = round(convertUom(area, "sqm", unit), 2);
 
         return output + " " + label;
     };
diff --git a/web/client/components/mapcontrols/measure/MeasureComponent.jsx b/web/client/components/mapcontrols/measure/MeasureComponent.jsx
index eed3c39d40..4456ddc440 100644
--- a/web/client/components/mapcontrols/measure/MeasureComponent.jsx
+++ b/web/client/components/mapcontrols/measure/MeasureComponent.jsx
@@ -13,7 +13,7 @@ const ToggleButton = require('../../buttons/ToggleButton');
 const NumberFormat = require('../../I18N/Number');
 const Message = require('../../I18N/Message');
 const {DropdownList} = require('react-widgets');
-const measureUtils = require('../../../utils/MeasureUtils');
+const {convertUom, getFormattedBearingValue} = require('../../../utils/MeasureUtils');
 const localeUtils = require('../../../utils/LocaleUtils');
 
 const {isEqual, round} = require('lodash');
@@ -104,9 +104,9 @@ class MeasureComponent extends React.Component {
         lengthLabel: <Message msgId="measureComponent.lengthLabel"/>,
         areaLabel: <Message msgId="measureComponent.areaLabel"/>,
         bearingLabel: <Message msgId="measureComponent.bearingLabel"/>,
-        formatLength: (uom, value) => measureUtils.getFormattedLength(uom, value),
-        formatArea: (uom, value) => measureUtils.getFormattedArea(uom, value),
-        formatBearing: (value) => measureUtils.getFormattedBearingValue(round(value || 0, 6)),
+        formatLength: (uom, value) => convertUom(value, "m", uom),
+        formatArea: (uom, value) => convertUom(value, "sqm", uom),
+        formatBearing: (value) => getFormattedBearingValue(round(value || 0, 6)),
         onChangeUom: () => {}
     };
 
diff --git a/web/client/plugins/map/index.js b/web/client/plugins/map/index.js
index 901ebf2fec..3b71837e61 100644
--- a/web/client/plugins/map/index.js
+++ b/web/client/plugins/map/index.js
@@ -47,6 +47,7 @@ module.exports = (mapType, actions) => {
 
     const MeasurementSupport = connect((state) => ({
         measurement: state.measurement || {},
+        useTreshold: state.measurement && state.measurement.useTreshold || null,
         uom: state.measurement && state.measurement.uom || {
             length: {unit: 'm', label: 'm'},
             area: {unit: 'sqm', label: 'm²'}
diff --git a/web/client/utils/MeasureUtils.js b/web/client/utils/MeasureUtils.js
index 8012b4cdae..390454b5c4 100644
--- a/web/client/utils/MeasureUtils.js
+++ b/web/client/utils/MeasureUtils.js
@@ -33,83 +33,116 @@ function getFormattedBearingValue(azimuth = 0) {
     return bearing;
 }
 
-function mToft(length) {
-    return length * 3.28084;
-}
-
-function mTokm(length) {
-    return length * 0.001;
-}
-
-function mTomi(length) {
-    return length * 0.000621371;
-}
-
-function mTonm(length) {
-    return length * 0.000539956803;
-}
-
-function sqmTosqft(area) {
-    return area * 10.7639;
-}
 
-function sqmTosqkm(area) {
-    return area * 0.000001;
-}
-
-function sqmTosqmi(area) {
-    return area * 0.000000386102159;
-}
-function sqmTosqnm(area) {
-    return area * 0.00000029155;
-}
-
-function getFormattedLength(unit = "m", length = 0) {
-    switch (unit) {
-    case 'm':
-        return length;
-    case 'ft':
-        return mToft(length);
-    case 'km':
-        return mTokm(length);
-    case 'mi':
-        return mTomi(length);
-    case 'nm':
-        return mTonm(length);
-    default:
-        return length;
+const CONVERSION_RATE = {
+    // length
+    "yd": {
+        "ft": 3,
+        "m": 0.9144,
+        "km": 0.0009144,
+        "yd": 1,
+        "mi": 0.00056818181818,
+        "nm": 0.00049373650107
+    },
+    "ft": {
+        "ft": 1,
+        "m": 0.3048,
+        "km": 0.0003048,
+        "yd": 0.33333333333334,
+        "mi": 0.0001893932,
+        "nm": 0.000164579
+    },
+    "m": {
+        "ft": 3.28084,
+        "m": 1,
+        "km": 0.001,
+        "yd": 1.0936132983377,
+        "mi": 0.000621371,
+        "nm": 0.000539956803
+    },
+    "km": {
+        "ft": 3280.84,
+        "m": 1000,
+        "km": 1,
+        "yd": 1093.6132983377,
+        "mi": 0.62137121212121,
+        "nm": 0.53995682073433948212
+    },
+    "mi": {
+        "ft": 5280.0001689599821475,
+        "m": 1609.3440514990027168,
+        "km": 1.6093440514990027257,
+        "yd": 1760,
+        "mi": 1,
+        "nm": 0.86897626970788488521
+    },
+    "nm": {
+        "ft": 6076.1156799999789655,
+        "m": 1852.0000592639937622,
+        "km": 1.8520000592639938031,
+        "yd": 2025.3718285214,
+        "mi": 1.1507794848484809158,
+        "nm": 1
+    },
+    "sqft": {
+        "sqft": 1,
+        "sqm": 0.09290304,
+        "sqkm": 9.2903043596611E-8,
+        "sqmi": 3.587E-8,
+        "sqnm": 2.7051601137505E-8
+    },
+    "sqyd": {
+        "sqft": 8.9999247491639,
+        "sqm": 0.83612040133779,
+        "sqkm": 8.3612040133779e-7,
+        "sqyd": 1,
+        "sqmi": 3.228278917579e-7,
+        "sqnm": 2.4346237458194e-7
+    },
+    // area
+    "sqm": {
+        "sqft": 10.76391,
+        "sqm": 1,
+        "sqkm": 1.0E-6,
+        "sqyd": 1.196,
+        "sqmi": 3.8610215854245e-7,
+        "sqnm": 2.91181e-7
+    },
+    "sqkm": {
+        "sqft": 10763910,
+        "sqm": 1.0E6,
+        "sqkm": 1,
+        "sqyd": 1196000,
+        "sqmi": 0.38610215854245,
+        "sqnm": 0.291181
+    },
+    "sqmi": {
+        "sqft": 27878398.920726,
+        "sqm": 2589988.110336,
+        "sqkm": 2.589988110336,
+        "sqyd": 27878398.920726,
+        "sqmi": 1,
+        "sqnm": 0.75415532795574
+    },
+    "sqnm": {
+        "sqft": 36966388.603652,
+        "sqm": 3434290.0120544,
+        "sqkm": 3.4342900120544,
+        "sqyd": 36966388.603652,
+        "sqmi": 1.325986786715,
+        "sqnm": 1
     }
-}
+};
 
-function getFormattedArea(unit = "sqm", area = 0) {
-    switch (unit) {
-    case 'sqm':
-        return area;
-    case 'sqft':
-        return sqmTosqft(area);
-    case 'sqkm':
-        return sqmTosqkm(area);
-    case 'sqmi':
-        return sqmTosqmi(area);
-    case 'sqnm':
-        return sqmTosqnm(area);
-    default:
-        return area;
+function convertUom(value, source = "m", dest = "m") {
+    if (!!CONVERSION_RATE[source] && !!CONVERSION_RATE[source][dest]) {
+        return value * CONVERSION_RATE[source][dest];
     }
+    return value;
 }
 
-
 module.exports = {
+    convertUom,
     getFormattedBearingValue,
-    getFormattedLength,
-    getFormattedArea,
-    degToDms,
-    mToft,
-    mTokm,
-    mTomi,
-    mTonm,
-    sqmTosqmi,
-    sqmTosqkm,
-    sqmTosqnm,
-    sqmTosqft
+    degToDms
 };
diff --git a/web/client/utils/__tests__/MeasureUtils-test.js b/web/client/utils/__tests__/MeasureUtils-test.js
index 614a9755b0..272f9943d2 100644
--- a/web/client/utils/__tests__/MeasureUtils-test.js
+++ b/web/client/utils/__tests__/MeasureUtils-test.js
@@ -8,17 +8,8 @@
 const expect = require('expect');
 const {
     getFormattedBearingValue,
-    getFormattedLength,
-    getFormattedArea,
     degToDms,
-    mToft,
-    mTokm,
-    mTomi,
-    mTonm,
-    sqmTosqmi,
-    sqmTosqkm,
-    sqmTosqnm,
-    sqmTosqft
+    convertUom
 } = require('../MeasureUtils');
 
 
@@ -28,67 +19,60 @@ describe('MeasureUtils', () => {
     });
     afterEach(() => {
 
+    });
+    it('test conversion km to mi', () => {
+        const val = convertUom(1, "km", "mi");
+        expect(val).toBe(0.62137121212121);
     });
     it('test conversion meters to feet', () => {
-        const val = mToft(1);
+        const val = convertUom(1, "m", "ft");
         expect(val).toBe(3.28084);
     });
     it('test conversion meters to kilometers', () => {
-        const val = mTokm(1);
+        const val = convertUom(1, "m", "km");
         expect(val).toBe(0.001);
     });
     it('test conversion meters to miles', () => {
-        const val = mTomi(1);
+        const val = convertUom(1, "m", "mi");
         expect(val).toBe(0.000621371);
     });
     it('test conversion meters to nauticalmiles', () => {
-        const val = mTonm(1);
+        const val = convertUom(1, "m", "nm");
         expect(val).toBe(0.000539956803);
     });
     it('test conversion squaremeters to squarefeet', () => {
-        const val = sqmTosqft(1);
-        expect(val).toBe(10.7639);
+        const val = convertUom(1, "sqm", "sqft");
+        expect(val).toBe(10.76391);
     });
     it('test conversion squaremeters to squarekilometers', () => {
-        const val = sqmTosqkm(1);
+        const val = convertUom(1, "sqm", "sqkm");
         expect(val).toBe(0.000001);
     });
     it('test conversion squaremeters to squaremiles', () => {
-        const val = sqmTosqmi(1);
-        expect(val).toBe(0.000000386102159);
+        const val = convertUom(1, "sqm", "sqmi");
+        expect(val).toBe(3.8610215854245e-7);
     });
     it('test conversion squaremeters to squarenauticalmiles', () => {
-        const val = sqmTosqnm(1);
-        expect(val).toBe(0.00000029155);
-    });
-    it('test getFormattedLength', () => {
-        let val = getFormattedLength("m", 1);
-        expect(val).toBe(1);
-        val = getFormattedLength(undefined, 1);
-        expect(val).toBe(1);
-        val = getFormattedLength("ft", 1);
-        expect(val).toBe(3.28084);
-        val = getFormattedLength("km", 1);
-        expect(val).toBe(0.001);
-        val = getFormattedLength("mi", 1);
-        expect(val).toBe(0.000621371);
-        val = getFormattedLength("nm", 1);
-        expect(val).toBe(0.000539956803);
+        const val = convertUom(1, "sqm", "sqnm");
+        expect(val).toBe(2.91181e-7);
     });
-    it('test getFormattedArea', () => {
-        let val = getFormattedArea("sqm", 1);
-        expect(val).toBe(1);
-        val = getFormattedArea(undefined, 1);
-        expect(val).toBe(1);
-        val = getFormattedArea("sqft", 1);
-        expect(val).toBe(10.7639);
-        val = getFormattedArea("sqkm", 1);
-        expect(val).toBe(0.000001);
-        val = getFormattedArea("sqmi", 1);
-        expect(val).toBe(0.000000386102159);
-        val = getFormattedArea("sqnm", 1);
-        expect(val).toBe(0.00000029155);
+    it('test conversion squarefeets to squarekilometers', () => {
+        const val = convertUom(1, "sqft", "sqkm");
+        expect(val).toBe(9.2903043596611e-8);
+    });
+    it('test conversion squarekilometers to squaremiles', () => {
+        const val = convertUom(1, "sqkm", "sqmi");
+        expect(val).toBe(0.38610215854245);
+    });
+    it('test conversion squaremiles to squarenauticalmiles', () => {
+        const val = convertUom(1, "sqmi", "sqnm");
+        expect(val).toBe(0.75415532795574);
     });
+    it('test conversion squarenauticalmiles to squaremiles', () => {
+        const val = convertUom(1, "sqnm", "sqmi");
+        expect(val).toBe(1.325986786715);
+    });
+
     it('test degToDms', () => {
         let val = degToDms(1.111);
         expect(val).toBe("1° 6' 39'' ");