001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.osm.visitor.paint;
003
004import org.openstreetmap.josm.gui.MapViewState.MapViewPoint;
005import org.openstreetmap.josm.gui.draw.MapPath2D;
006import org.openstreetmap.josm.tools.Utils;
007
008/**
009 * This class helps with painting arrows with fixed length along a path.
010 * @author Michael Zangl
011 * @since 10827
012 */
013public class ArrowPaintHelper {
014    private final double sin;
015    private final double cos;
016    private final double length;
017
018    /**
019     * Creates a new arrow helper.
020     * @param radians The angle of the arrow. 0 means that it lies on the current line. In radians
021     * @param length The length of the arrow lines.
022     */
023    public ArrowPaintHelper(double radians, double length) {
024        this.sin = Math.sin(radians);
025        this.cos = Math.cos(radians);
026        this.length = length;
027    }
028
029    /**
030     * Paint the arrow
031     * @param path The path to append the arrow to.
032     * @param point The point to paint the tip at
033     * @param fromDirection The direction the line is comming from.
034     */
035    public void paintArrowAt(MapPath2D path, MapViewPoint point, MapViewPoint fromDirection) {
036        double x = point.getInViewX();
037        double y = point.getInViewY();
038        double dx = fromDirection.getInViewX() - x;
039        double dy = fromDirection.getInViewY() - y;
040        double norm = Math.sqrt(dx * dx + dy * dy);
041        if (norm > 1e-10) {
042            dx *= length / norm;
043            dy *= length / norm;
044            path.moveTo(x + dx * cos + dy * sin, y + dx * -sin + dy * cos);
045            if (!Utils.equalsEpsilon(cos, 0)) {
046                path.lineTo(point);
047            }
048            path.lineTo(x + dx * cos + dy * -sin, y + dx * sin + dy * cos);
049        }
050    }
051
052    /**
053     * Gets the length of the arrow along the line segment.
054     * @return the length along the line
055     * @since 12154
056     */
057    public double getOnLineLength() {
058        return length * cos;
059    }
060}