Opened 22 months ago
Last modified 14 months ago
#22695 new enhancement
MAPCSS, Note on: icon-rotation: way; text-rotation: way; coordinate transformation, documentation
Reported by: | mikeho | Owned by: | team |
---|---|---|---|
Priority: | normal | Milestone: | |
Component: | Core | Version: | |
Keywords: | mapcss, text and icon rotation | Cc: | gaben |
Description
Hallo,
I have some comments on the MAPCSS implementation based on my experience of displaying railway signals:
0- Preliminary remark:
Direction is given in degrees in the world coordinate system: 0° - north, 90° - east, 180° - south, 270° - west.
In the usual coordinate system, the x-axis is oriented from west to east, the y-axis from south to north (example JOSM: text-offset-y) or from north to south (example screen, JOSM: icon-offset-y).
1- icon-rotation: way
node[...] {... icon-rotation: way; ...}
The icon is rotated along the y-axis. This results in a 90° counter-clockwise rotation of the icon. I haven't found a way to correct this (e.g. icon-rotation: way + 90deg; or icon-rotation: get_angle_of(way) + 90deg; (function 'get_angle_of' does not exist).
My solution: Currently, corresponding images must be stored for: 0° for normal, +90° rotated for forward, +270° rotated for backward orientation.
In the documentation corresponding hints are missing, see https://josm.openstreetmap.de/wiki/Help/Styles/MapCSSImplementation
In the further development of the MAPCSS implementation in JOSM, the mathematical change of the rotation (... way + 90deg ... should be possible) should be taken into account. Addition: The coordinate system should rotate accordingly (not ... icon-rotation: way; ... (y-axis to the right of way), but ... icon-rotation: (way + 90deg); .... here: x-axis right of way)
2- Coordinate system: icon-rotation: way;
node[...] {... icon-rotation: way; ...}
The coordinate system rotates with: that's good !
3- Coordinate system: text-rotation: way;
node[...] {... text-rotation: way; ...}
Coordinate system does not rotate with. The result is that text can be moved in the west-east direction, but not relative to the way. With the consequence that text (e.g. value of a button) cannot be placed exactly above the icon.
I suggest (urgently) to create an additional possibility for positioning the text in the rotated coordinate system, e.g. text-offset-x, text-offset-y or rotated-text-offset-x, rotated-text-offset-y (analogous to icon-offset-x, text-offset-y).
4- Documentation
Appropriate documentation is welcome, see: https://josm.openstreetmap.de/wiki/Help/Styles/MapCSSImplementation. It helps Newcommer to understand and apply.
best begrads
mikeho
Attachments (11)
Change History (32)
by , 22 months ago
Attachment: | JOSM_demo.zip added |
---|
by , 22 months ago
Attachment: | 0001-Fix-mapcss-rotation-offset-for-rotation-way.patch added |
---|
by , 22 months ago
Attachment: | 0002-Add-parent_way_angle-mapcss-function.patch added |
---|
comment:2 by , 22 months ago
I added two patches that (1) fix the 90° offset and (2) add a parent_way_angle
mapcss function (as discussed here)
I don't have my usual dev setup at the moment so the patches might be in the incorrect format
comment:4 by , 22 months ago
When will the function "rotation_parent_way" be available?
I have attached a file to illustrate the challenge. It is important that the rotated text, in the coordinate system rotated on the parent way, can be moved (offset-x, offset-Y) as well as the icon. Only this allows the exact positioning of the individual elements (icons and texts) to an composed icon.
by , 22 months ago
Attachment: | icon-text-rotation.pdf added |
---|
comment:5 by , 22 months ago
The function will be called parent_way_angle
. Check #22704 for status updates related to that.
Offset relative to the rotated coordinate system is pending until someone implements it
comment:6 by , 22 months ago
Summary: | MAPCSS, Note on: icon-rotation: way; text-rotation: way; coordinate transformation, documentation → MAPCSS, Note on: icon-rotation: way; text-rotation: way; coordinate transformation, documentation [patch] |
---|
comment:7 by , 22 months ago
Summary: | MAPCSS, Note on: icon-rotation: way; text-rotation: way; coordinate transformation, documentation [patch] → MAPCSS, Note on: icon-rotation: way; text-rotation: way; coordinate transformation, documentation |
---|
Patches are in separate tickets now.
Replying to Woazboat:
Okay so there's multiple TODOs here:
1)*-rotation: way;
needs to be documented
It is a wiki, feel free to add and update the documentation.
follow-up: 10 comment:9 by , 22 months ago
I think I have this problem already solved in my 'personal edition' of JOSM.
Demonstration of rotated icon + text + additional panels:
My implementation adds a mapcss-function heading()
, that you use this way:
node.sign[direction=forward] { icon-rotation: heading(); } node.sign[direction=backward] { icon-rotation: eval(heading() + 3.14); }
You can test my version starting here:
https://github.com/MarcelloPerathoner/josm
The traffic-sign stylesheet is in the incubating
directory.
If you like this, I can create a pull-request.
follow-up: 17 comment:10 by , 22 months ago
Replying to marcello@…:
My implementation adds a mapcss-function
heading()
, that you use this way:
Sounds similar to #22704
What's missing is the text rotation and offset anchor (i.e. whether the offset should also be rotated)
comment:11 by , 22 months ago
But if you have made improvements for josm, why keep them in your 'personal implementation' and not upstream them?
follow-up: 13 comment:12 by , 22 months ago
Similar, but mine is more flexible: you can rotate forward and backward and any other angle you want in relation to the way.
I don't quite see why you'd want to rotate around any other centerpoint than the node itself. Can you name a use case? If there's a use case for more complex transformations we should better implement all transformation functions like in CSS, so that you can say, e.g.:
text-transform: translate(-x, -y, rotate(heading() + 3.14, translate(x, y)));
or
icon-transform: matrix(a, b, c, d, e, f);
As for why I'm not upstreaming: I would, but I doubt the maintainers would accept so big a patch and its hard to split up into smaller ones because its all connected. But the rotation thingie would split off easily.
follow-up: 14 comment:13 by , 22 months ago
Replying to marcello@…:
Similar, but mine is more flexible: you can rotate forward and backward and any other angle you want in relation to the way.
Not sure why it would be more flexible? The only difference is the name of the function and that your version tries to pick the 'correct' parent ways by itself vs. the one in #22704 uses the one matched via mapcss child selectors.
I don't quite see why you'd want to rotate around any other centerpoint than the node itself. Can you name a use case? If there's a use case for more complex transformations we should better implement all transformation functions like in CSS, so that you can say, e.g.:
text-transform: translate(-x, -y, rotate(heading() + 3.14, translate(x, y)));
or
icon-transform: matrix(a, b, c, d, e, f);
The center point would still be the node, only the translation coordinate system would be rotated. As for use cases, ask the OP of this issue who requested this.
follow-up: 16 comment:14 by , 22 months ago
Replying to Woazboat:
Not sure why it would be more flexible? The only difference is the name of the function and that your version tries to pick the 'correct' parent ways by itself vs. the one in #22704 uses the one matched via mapcss child selectors.
I meant that icon-rotation: way
does not allow to specify a backward-facing sign. (Or does it? Its undocumented.)
The function parent_way_angle
OTOH needs to be told exactly one way to use. It does not bisect angles. What happens if the node is at a junction of two ways, as many traffic signs are?
My function works well at the junction of two ways. It also bisects the angle, which looks slightly better.
The use case illustrated in the PDF is fully covered by my version.
BTW. in your patch 0002 you refer to the "child selector" but your link points to the "link selector".
by , 22 months ago
Attachment: | Screenshot from 2023-02-15 21-13-39.png added |
---|
Screenshot Icon and Text Offset and Rotated
comment:15 by , 22 months ago
comment:16 by , 22 months ago
Replying to marcello@…:
Replying to Woazboat:
Not sure why it would be more flexible? The only difference is the name of the function and that your version tries to pick the 'correct' parent ways by itself vs. the one in #22704 uses the one matched via mapcss child selectors.
I meant that
icon-rotation: way
does not allow to specify a backward-facing sign. (Or does it? Its undocumented.)
Ah, no that has a fixed rotation in the way direction. I was referring to the parent_way_angle()
mapcss function though.
The function
parent_way_angle
OTOH needs to be told exactly one way to use. It does not bisect angles. What happens if the node is at a junction of two ways, as many traffic signs are?
My function works well at the junction of two ways. It also bisects the angle, which looks slightly better.
Being able to specifically select the parent way via the child selector is a feature. If there are multiple potential parents, the matching code IIRC simply picks the first one (could be that I'm misremembering this). That's a limitation of the mapcss matching though and not specific to this function.
Your parent discovery method is useful if there is no specified parent or if there are multiple, so maybe that could be merged together.
The angle was chosen to be similar to the already existing implementation for *-rotation: way;
. It would be confusing if those two used different angles. Bisecting angles would probably be better, but that'd have to be changed for both *-rotation: way;
and for parent_way_angle()
.
The use case illustrated in the PDF is fully covered by my version.
The missing pieces would be useful to have in josm.
BTW. in your patch 0002 you refer to the "child selector" but your link points to the "link selector".
Ah, true. I think that's because the documentation for the parent
object in the mapcss environment linked to the LinkSelector and I copied that.
comment:17 by , 22 months ago
Replying to Woazboat:
offset anchor (i.e. whether the offset should also be rotated)
Replying to Woazboat:
The center point would still be the node, only the translation coordinate system would be rotated.
This is similar to what I meant, just with an additional option to use the icon/text rotation as the reference: https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#paint-symbol-icon-translate-anchor
Frame of reference is probably the better term.
comment:18 by , 21 months ago
Note regarding the above discussion:
OK - there are styles that do not need rotation. Three examples are attached (direction of osm-way, maxspeed as text, railway switches).
For railroad signals the rotation of the icon and the text is required. I have attached this style - in the current development state - as well.
Signals are usually tagged only to nodes that belong to a way. The possible ambiguity can therefore be neglected in my opinion.
by , 21 months ago
Attachment: | direction_of_osm_way.zip added |
---|
by , 21 months ago
Attachment: | maxspeed_as_text.mapcss added |
---|
by , 21 months ago
Attachment: | switch.zip added |
---|
by , 21 months ago
Attachment: | railway_signal_ger.zip added |
---|
by , 21 months ago
Attachment: | Screenshot_20230220_133732.png added |
---|
Screenshot of railway speed limit sign with rotated text
comment:21 by , 14 months ago
Cc: | added |
---|
I was thinking about a feature some time ago. For give way and passing place - if they have sides defined - would be very useful. Although, I believe it requires some testing to see how these small icons behave with rotation.
Okay so there's multiple TODOs here:
1)
*-rotation: way;
needs to be documented2) 90 degree offset of
*-rotation: way;
compared to*-rotation: <fixed angle>
The 90 degree offset occurs because https://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/tools/RotationAngle.java#L37 uses
Geometry.getSegmentAngle
, which calculates the angle usingMath.atan2
and therefore the rotation starting from the x-axis (east) in counter clockwise direction. The icon rotation is relative to the icon and therefore 'starts' at the y-axis (north) going in the clockwise direction.The returned angle is correctly inverted to fix the rotation angle, but the 90° offset is not corrected. This can be fixed by adding an offset of
- Math.PI/2
to the angle (+Math.PI/2
if done after inversion).