#21982 closed enhancement (wontfix)
Add MapCSS feet-and-inches to meters eval function
Reported by: | happy5214 | Owned by: | team |
---|---|---|---|
Priority: | normal | Milestone: | |
Component: | Core mappaint | Version: | |
Keywords: | Cc: |
Description
Currently, the procedure for converting an OSM length tag value in customary/imperial units (e.g. a road width) to meters is extremely clunky, involving multiple conditionals and regexes. This may be the reason road widths using feet are not currently supported at all by the Lane and Road Attributes map style, which renders such roads using an unrealistic thin line (example attached; the north segment has a width of "40'", while the south segment has no width tag). I think this unit conversion would be more easily addressed in the JOSM code itself and then exposed as an eval function.
Attachments (1)
Change History (9)
by , 3 years ago
Attachment: | Screenshot_20220330_225501.png added |
---|
comment:1 by , 3 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
I'm not much in favour of further supporting non-metric units in the tags.
comment:2 by , 3 years ago
Americans should not be forced to make up metric conversions for tagging when values are legally defined (and constructed on-the-ground) in customary units. That's the data consumers' job.
comment:3 by , 3 years ago
We should be mapping what's on the ground. Like it or not, imperial measurements are here to stay in OSM, so long as countries still use them. It's no different from a country using one currency; a database should store values the way they're originally measured, not a conversion.
comment:4 by , 3 years ago
Since I've been told it's not exactly clear what I'm asking for, the request is for a MapCSS eval function that accepts a length value in either foot-inch format (e.g. 12'6"
) or meters (i.e. a decimal unit-less number) and returns the length value in meters. This would be added as a single static method in org.openstreetmap.josm.gui.mappaint.mapcss.Functions
.
comment:5 by , 3 years ago
I'll even volunteer this (untested) implementation of the eval function I'm looking for.
public static double feet_to_meters(String source) { try { return Double.parseDouble(source); } catch (NumberFormatException ex) { } List<String> matchList = Utils.getMatches(Pattern.compile("^(?:((?:\\d*\\.)?\\d+)\')?(?:((?:\\d*\\.)?\\d+)\")?$").matcher(source)); if (matchList != null) { double feet = matchList.get(1) == null ? 0.0 : Double.parseDouble(matchList.get(1)); double inches = matchList.get(2) == null ? 0.0 : Double.parseDouble(matchList.get(2)); inches += 12 * feet; return 0.0254 * inches; } else { return null; } }
Edit: I've greatly shortened the code above (still untested).
comment:6 by , 3 years ago
A couple of comments on the untested implementation:
1) The file to modify is source:trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Functions.java
2) Using exceptions can be expensive (from a perf standpoint). And silently hiding them tends to be a bad idea in general. In this case, you probably could get away with hiding it, but it should still be logged (e.g., Logging#trace
)
3) You should not compile a regex on every call. Regex compiling can be fairly expensive.
4) There are no unit tests (this is something that is external facing, so we pretty much cannot change it if we ever merge it).
As a comment on unit conversions, I'd rather have something like double convert_units(String source, String default_unit, String to_unit)
. Preferentially, the default_unit
and to_unit
would be an enum, but I'd have to look at the mapcss parsing code to see how possible that would be.
follow-up: 8 comment:7 by , 3 years ago
I never claimed this was a complete patch, re. the unit tests (for example, I didn't add the function to the ExpressionFactory
function list in that code, but I considered that relatively trivial).
- I'll have to look at the contributor's guide. Most of my work is with git, so I'm out of my element with svn.
- Is there a utility function to the effect of "string looks like a decimal number" I can use instead? That was the intent of that code.
- Should I make it a class constant?
- As I said above, I didn't think it was appropriate to write unit tests in a bug comment that wasn't an actual patch. I was told on OSMUS Slack to write a PoC to explain the requested feature (and the relative ease of implementation), and that's what I came up with.
A general convert_units
function would be nice, but OSM doesn't write feet and inches using ft
and in
. The consensus is to use prime/double-prime notation (as I gave above) for those units.
comment:8 by , 3 years ago
Replying to happy5214:
- I'll have to look at the contributor's guide. Most of my work is with git, so I'm out of my element with svn.
https://github.com/JOSM/josm/ (JOSM SVN mirror on GitHub)
- Is there a utility function to the effect of "string looks like a decimal number" I can use instead? That was the intent of that code.
- Should I make it a class constant?
Not yet. If you look at the linked file, you'll notice that patterns are created once on class load (static final Pattern
). I do tend to find myself creating regexes to check for numbers a lot. One of the patches I've got floating around somewhere created a PatternUtils
class to cache patterns. I don't remember which ticket I was using that for though.
- As I said above, I didn't think it was appropriate to write unit tests in a bug comment that wasn't an actual patch. I was told on OSMUS Slack to write a PoC to explain the requested feature (and the relative ease of implementation), and that's what I came up with.
It probably would not be too difficult to do a basic implementation to convert units from imperial to metric. However, other programs use JOSM mapcss syntax (for example, I believe Osmose uses JOSM mapcss for some of its checks). So anything that would be non-JOSM specific has to be more thought out, as it may become an implementation detail that cannot easily be fixed later. A function to convert a specific type of unit to another specific type of unit is easy to do. But this can lead to many more public functions (e.g., chinese_to_metric
, metric_to_chinese
, nautical_to_metric
, metric_to_nautical
, etc.). Those could all be private
functions, but that would be an implementation detail, not something public facing.
A general
convert_units
function would be nice, but OSM doesn't write feet and inches usingft
andin
. The consensus is to use prime/double-prime notation (as I gave above) for those units.
My bad -- I was thinking of something like IMPERIAL
and METRIC
(see source:trunk/src/org/openstreetmap/josm/data/SystemOfMeasurement.java for currently supported systems of measurement).
Example of Lane and Road Attributes map paint style when using customary units (north segment has width=40') for road width, compared to the default setting. Two sidewalks and infrastructure are also present.