Ticket #10217: 10217.patch

File 10217.patch, 7.0 KB (added by simon04, 5 years ago)
  • src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java

    diff --git a/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java b/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
    index 1f997ed..fc06343 100644
    a b public class StyledMapRenderer extends AbstractMapRenderer { 
    666666        }
    667667    }
    668668
    669     public void drawNodeIcon(Node n, Image img, float alpha, boolean selected, boolean member) {
     669    public void drawNodeIcon(Node n, Image img, float alpha, boolean selected, boolean member, double theta) {
    670670        Point p = nc.getPoint(n);
    671671
    672672        final int w = img.getWidth(null), h=img.getHeight(null);
    public class StyledMapRenderer extends AbstractMapRenderer { 
    677677        if (alpha != 1f) {
    678678            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
    679679        }
     680        g.rotate(theta, p.x, p.y);
    680681        g.drawImage(img, p.x-w/2, p.y-h/2, nc);
     682        g.rotate(-theta, p.x, p.y);
    681683        g.setPaintMode();
    682684        if (selected || member)
    683685        {
  • src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java

    diff --git a/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java b/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java
    index 47a0a6c..30cef80 100644
    a b import org.openstreetmap.josm.Main; 
    1212import org.openstreetmap.josm.data.osm.Node;
    1313import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1414import org.openstreetmap.josm.data.osm.Relation;
     15import org.openstreetmap.josm.data.osm.Way;
    1516import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
    1617import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
    1718import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.BoxProvider;
    1819import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.SimpleBoxProvider;
    1920import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
    2021import org.openstreetmap.josm.gui.mappaint.StyleCache.StyleList;
     22import org.openstreetmap.josm.tools.Geometry;
     23import org.openstreetmap.josm.tools.SubclassFilteredCollection;
    2124import org.openstreetmap.josm.tools.Utils;
    2225
    2326/**
    import org.openstreetmap.josm.tools.Utils; 
    2528 */
    2629public class NodeElemStyle extends ElemStyle implements StyleKeys {
    2730    public final MapImage mapImage;
     31    public final IconRotation mapImageAngle;
    2832    public final Symbol symbol;
    2933
    3034    private Image enabledNodeIcon;
    public class NodeElemStyle extends ElemStyle implements StyleKeys { 
    96100    public static final StyleList DEFAULT_NODE_STYLELIST = new StyleList(NodeElemStyle.SIMPLE_NODE_ELEMSTYLE);
    97101    public static final StyleList DEFAULT_NODE_STYLELIST_TEXT = new StyleList(NodeElemStyle.SIMPLE_NODE_ELEMSTYLE, BoxTextElemStyle.SIMPLE_NODE_TEXT_ELEMSTYLE);
    98102
    99     protected NodeElemStyle(Cascade c, MapImage mapImage, Symbol symbol, float default_major_z_index) {
     103    /**
     104     * Determines how an icon is to be rotated depending on the primitive to displayed.
     105     */
     106    public static abstract class IconRotation {
     107        /**
     108         * Calculates the rotation angle depending on the primitive to displayed.
     109         */
     110        public abstract double getRotationAngle(OsmPrimitive p);
     111
     112        /**
     113         * Always returns the fixed {@code angle}.
     114         */
     115        public static IconRotation buildStaticRotation(final double angle) {
     116            return new IconRotation() {
     117                @Override
     118                public double getRotationAngle(OsmPrimitive p) {
     119                    return angle;
     120                }
     121            };
     122        }
     123
     124        /**
     125         * Computes the angle depending on the referencing way segment, or {@code 0} if none exists.
     126         */
     127        public static IconRotation buildWayDirectionRotation() {
     128            return new IconRotation() {
     129                @Override
     130                public double getRotationAngle(OsmPrimitive p) {
     131                    if (!(p instanceof Node)) {
     132                        return 0;
     133                    }
     134                    final Node n = (Node) p;
     135                    final SubclassFilteredCollection<OsmPrimitive, Way> ways = Utils.filteredCollection(n.getReferrers(), Way.class);
     136                    if (ways.isEmpty()) {
     137                        return 0;
     138                    }
     139                    final Way w = ways.iterator().next();
     140                    final int idx = w.getNodes().indexOf(n);
     141                    if (idx == 0) {
     142                        return -Geometry.getSegmentAngle(n.getEastNorth(), w.getNode(idx + 1).getEastNorth());
     143                    } else {
     144                        return -Geometry.getSegmentAngle(w.getNode(idx - 1).getEastNorth(), n.getEastNorth());
     145                    }
     146                }
     147            };
     148        }
     149    }
     150
     151    protected NodeElemStyle(Cascade c, MapImage mapImage, Symbol symbol, float default_major_z_index, IconRotation iconRotation) {
    100152        super(c, default_major_z_index);
    101153        this.mapImage = mapImage;
    102154        this.symbol = symbol;
     155        this.mapImageAngle = iconRotation;
    103156    }
    104157
    105158    public static NodeElemStyle create(Environment env) {
    public class NodeElemStyle extends ElemStyle implements StyleKeys { 
    114167        if (mapImage == null) {
    115168            symbol = createSymbol(env);
    116169        }
     170        final IconRotation iconRotation;
     171        final Float rotationFloat = c.get("icon-rotation", null, Float.class);
     172        if (rotationFloat != null) {
     173            iconRotation = IconRotation.buildStaticRotation(Math.toRadians(rotationFloat));
     174        } else if ("way".equalsIgnoreCase(c.get("icon-rotation", null, String.class))) {
     175            iconRotation = IconRotation.buildWayDirectionRotation();
     176        } else {
     177            iconRotation = null;
     178        }
    117179
    118180        // optimization: if we neither have a symbol, nor a mapImage
    119181        // we don't have to check for the remaining style properties and we don't
    120182        // have to allocate a node element style.
    121183        if (!allowDefault && symbol == null && mapImage == null) return null;
    122184
    123         return new NodeElemStyle(c, mapImage, symbol, default_major_z_index);
     185        return new NodeElemStyle(c, mapImage, symbol, default_major_z_index, iconRotation);
    124186    }
    125187
    126188    public static MapImage createIcon(final Environment env, final String[] keys) {
    public class NodeElemStyle extends ElemStyle implements StyleKeys { 
    258320                    }
    259321                    nodeIcon = enabledNodeIcon;
    260322                }
    261                 painter.drawNodeIcon(n, nodeIcon, Utils.color_int2float(mapImage.alpha), selected, member);
     323                painter.drawNodeIcon(n, nodeIcon, Utils.color_int2float(mapImage.alpha), selected, member,
     324                        mapImageAngle == null ? 0.0 : mapImageAngle.getRotationAngle(primitive));
    262325            } else if (symbol != null) {
    263326                Color fillColor = symbol.fillColor;
    264327                if (fillColor != null) {