Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/codespell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ jobs:
with:
check_filenames: true
skip: ./.git,./data/territory_languages.json,./data/imagery.json,./data/languages.json,./data/address_formats.json,./dist/locales,./docs/img,./dist/img
ignore_words_list: "auxilary,casette,cemetary,chancel,childs,extentions,falsy,files',froms,generat,guerilla,inflight,kindergarden,nd,specialties,tos,vias,visibles"
ignore_words_list: "auxilary,casette,cemetary,chancel,childs,extentions,falsy,files',fillL,froms,generat,guerilla,inflight,kindergarden,nd,ot,pavillion,specialties,tos,vias,visibles"
exclude_file: .codespellignorelines
only_warn: 1
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ _Breaking developer changes, which may affect downstream projects or sites that
* Hide tag suggestions for tags like `name_1` in raw tag editor autocomplete ([#9422])
* Show `(empty)` as a tag value option in the raw tag editor when a multi selections contains at least one feature which does not have the particular tag ([#9876], thanks [@k-yle])
* Allow to search for OSM notes by id in search bar ([#10062], thanks [@NaVis0mple])
* Add support for coordinates in `<degree> <minutes>[ <seconds>]` format to search bar ([#10066], thanks [@NaVis0mple])
#### :scissors: Operations
#### :camera: Street-Level
#### :white_check_mark: Validation
Expand All @@ -66,6 +67,7 @@ _Breaking developer changes, which may affect downstream projects or sites that
[#9983]: https://github.com/openstreetmap/iD/issues/9983
[#9992]: https://github.com/openstreetmap/iD/issues/9992
[#10062]: https://github.com/openstreetmap/iD/pull/10062
[#10066]: https://github.com/openstreetmap/iD/pull/10066
[id-tagging-schema#1076]: https://github.com/openstreetmap/id-tagging-schema/pull/1076
[@ramith-kulal]: https://github.com/ramith-kulal
[@mangerlahn]: https://github.com/mangerlahn
Expand Down
4 changes: 2 additions & 2 deletions modules/ui/feature_list.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as sexagesimal from '@mapbox/sexagesimal';

import { presetManager } from '../presets';
import { t } from '../core/localizer';
import { dmsCoordinatePair } from '../util/units';
import { dmsCoordinatePair, dmsMatcher } from '../util/units';
import { coreGraph } from '../core/graph';
import { geoSphericalDistance } from '../geo/geo';
import { geoExtent } from '../geo';
Expand Down Expand Up @@ -125,7 +125,7 @@ export function uiFeatureList(context) {

if (!q) return result;

var locationMatch = sexagesimal.pair(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
var locationMatch = sexagesimal.pair(q.toUpperCase()) || dmsMatcher(q);

if (locationMatch) {
var loc = [Number(locationMatch[0]), Number(locationMatch[1])];
Expand Down
3 changes: 3 additions & 0 deletions modules/util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,6 @@ export { utilUnicodeCharsTruncated } from './util';
export { utilUniqueDomId } from './util';
export { utilWrap } from './util';
export { utilCleanOsmString } from './util';

export { dmsCoordinatePair } from './units';
export { dmsMatcher } from './units';
102 changes: 80 additions & 22 deletions modules/util/units.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,33 +106,50 @@ function clamp(x, min, max) {
return Math.max(min, Math.min(x, max));
}

function roundToDecimal (target, decimalPlace) {
target = Number(target);
decimalPlace = Number(decimalPlace);
const factor = Math.pow(10, decimalPlace);
return Math.round(target * factor) / factor;
}

function displayCoordinate(deg, pos, neg) {
var locale = localizer.localeCode();
var min = (Math.abs(deg) - Math.floor(Math.abs(deg))) * 60;
var sec = (min - Math.floor(min)) * 60;
var displayDegrees = t('units.arcdegrees', {
quantity: Math.floor(Math.abs(deg)).toLocaleString(locale)
});
var displayCoordinate;
var locale = localizer.localeCode();

if (Math.floor(sec) > 0) {
displayCoordinate = displayDegrees +
var degreesFloor = Math.floor(Math.abs(deg));
var min = (Math.abs(deg) - degreesFloor) * 60;
var minFloor = Math.floor(min);
var sec = (min - minFloor) * 60;


// if you input 45°,90°0'0.5" , sec should be 0.5 instead 0.499999…
// in order to mitigate precision errors after calculating, round two time
// 0.499999… => 0.5
var fix = roundToDecimal(sec, 8);
// 0.5 => 1
var secRounded = roundToDecimal(fix, 0);

if (secRounded === 60) {
secRounded = 0;
minFloor += 1;
if (minFloor === 60) {
minFloor = 0;
degreesFloor += 1;
}
}
displayCoordinate =
t('units.arcdegrees', {
quantity: degreesFloor.toLocaleString(locale)
}) +
(minFloor !== 0 || secRounded !== 0 ?
t('units.arcminutes', {
quantity: Math.floor(min).toLocaleString(locale)
}) +
quantity: minFloor.toLocaleString(locale)
}) : '') +
(secRounded !== 0 ?
t('units.arcseconds', {
quantity: Math.round(sec).toLocaleString(locale)
});
} else if (Math.floor(min) > 0) {
displayCoordinate = displayDegrees +
t('units.arcminutes', {
quantity: Math.round(min).toLocaleString(locale)
});
} else {
displayCoordinate = t('units.arcdegrees', {
quantity: Math.round(Math.abs(deg)).toLocaleString(locale)
});
}
quantity: secRounded.toLocaleString(locale)
}) : '' );

if (deg === 0) {
return displayCoordinate;
Expand Down Expand Up @@ -168,3 +185,44 @@ export function decimalCoordinatePair(coord) {
longitude: wrap(coord[0], -180, 180).toFixed(OSM_PRECISION)
});
}

// Return the parsed value that @mapbox/sexagesimal can't parse
// return value format : [D, D] ex:[ 35.1861, 136.83161 ]
export function dmsMatcher(q) {
const matchers = [
// D M SS , D M SS ex: 35 11 10.1 , 136 49 53.8
Comment thread
laigyu marked this conversation as resolved.
{
condition: /^\s*(-?)\s*(\d+)\s+(\d+)\s+(\d+\.?\d*)\s*\,\s*(-?)\s*(\d+)\s+(\d+)\s+(\d+\.?\d*)\s*$/,
parser: function(q) {
const match = this.condition.exec(q);
const lat = (+match[2]) + (+match[3]) / 60 + (+match[4]) / 3600;
const lng = (+match[6]) + (+match[7]) / 60 + (+match[8]) / 3600;
const isNegLat = match[1] === '-' ? -lat : lat;
const isNegLng = match[5] === '-' ? -lng : lng;
const d = [isNegLat, isNegLng];

return d;
}
},
// D MM , D MM ex: 35 11.1683 , 136 49.8966
{
condition: /^\s*(-?)\s*(\d+)\s+(\d+\.?\d*)\s*\,\s*(-?)\s*(\d+)\s+(\d+\.?\d*)\s*$/,
parser: function(q) {
const match = this.condition.exec(q);
const lat = +match[2] + (+match[3]) / 60;
const lng = +match[5] + (+match[6]) / 60;
const isNegLat = match[1] === '-' ? -lat : lat;
const isNegLng = match[4] === '-' ? -lng : lng;
const d = [isNegLat, isNegLng];

return d;
}
}
];
for (const matcher of matchers) {
if (matcher.condition.test(q)){
return matcher.parser(q);
}
}
return null;
}
55 changes: 55 additions & 0 deletions test/spec/util/units.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
describe('iD.units', function() {
describe('dmsMatcher', function() {
it('parses D M SS format', function() {
var result = iD.dmsMatcher('35 11 10.1 , 136 49 53.8');
expect(result[0]).to.be.closeTo( 35.18614, 0.00001);
expect(result[1]).to.be.closeTo(136.83161, 0.00001);
});
it('parses D M SS format, with negative value', function() {
var result = iD.dmsMatcher('-35 11 10.1 , -136 49 53.8');
expect(result[0]).to.be.closeTo( -35.18614, 0.00001);
expect(result[1]).to.be.closeTo(-136.83161, 0.00001);
});

it('parses D MM format', function() {
var result = iD.dmsMatcher('35 11.1683 , 136 49.8966');
expect(result[0]).to.be.closeTo( 35.18614, 0.00001);
expect(result[1]).to.be.closeTo(136.83161, 0.00001);
});
it('parses D MM format, with negative value', function() {
var result = iD.dmsMatcher('-35 11.1683 , -136 49.8966');
expect(result[0]).to.be.closeTo( -35.18614, 0.00001);
expect(result[1]).to.be.closeTo(-136.83161, 0.00001);
});

it('handles invalid input', function() {
var result = iD.dmsMatcher('!@#$');
expect(result).to.be.null;
});
});

describe('dmsCoordinatePair', function() {
it('formats coordinate pair', function () {
var result = iD.dmsCoordinatePair([90 + 0.5/3600, 45]);
expect(result).to.be.eql('45°N, 90°0′1″E');
});
it('formats 0°', function () {
var result = iD.dmsCoordinatePair([0, 0]);
expect(result).to.be.eql('0°, 0°');
});
it('formats negative value', function () {
var result = iD.dmsCoordinatePair([-179, -90]);
expect(result).to.be.eql('90°S, 179°W');
});
it('formats 180° lng, should be E or W', function () {
// The longitude at this line can be given as either east or west.
var result = iD.dmsCoordinatePair([180, 0]);
expect(result).to.be.oneOf(['0°, 180°W', '0°, 180E°']);
});
it('formats value over 90°lat or 180°lng', function () {
var result = iD.dmsCoordinatePair([181, 91]);
expect(result).to.be.oneOf(['90°N, 179°W']);
});
});
});