001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.mappaint.styleelement.placement;
003
004import java.awt.geom.Point2D;
005import java.awt.geom.Rectangle2D;
006
007import org.openstreetmap.josm.gui.draw.MapViewPath;
008import org.openstreetmap.josm.gui.draw.MapViewPositionAndRotation;
009
010/**
011 * A strategy that places the label / icon so that is is on the area.
012 *
013 * The center of that place should be in the area, but the icon / label may overlap on the edges.
014 *
015 * @author Michael Zangl
016 * @since 11722
017 * @since 11748 moved to own file
018 */
019public final class PartiallyInsideAreaStrategy extends CompletelyInsideAreaStrategy {
020    /**
021     * An instance of this class.
022     */
023    public static final PartiallyInsideAreaStrategy INSTANCE = new PartiallyInsideAreaStrategy(0, 0);
024
025    private PartiallyInsideAreaStrategy(double offsetX, double offsetY) {
026        super(offsetX, offsetY);
027    }
028
029    @Override
030    public MapViewPositionAndRotation findLabelPlacement(MapViewPath path, Rectangle2D nb) {
031        MapViewPositionAndRotation inside = super.findLabelPlacement(path, nb);
032        if (inside != null) {
033            return inside;
034        }
035
036        double nbdx = Math.max(0, (nb.getWidth() - 20) / 2);
037        double nbdy = Math.max(0, (nb.getHeight() - 10) / 2);
038
039        if (nbdx < .5 && nbdy < .5) {
040            // we can't do any better
041            return null;
042        } else {
043            Rectangle2D smallNb = new Rectangle2D.Double(nb.getX() + nbdx, nb.getY() + nbdy,
044                    nb.getWidth() - 2 * nbdx, nb.getHeight() - 2 * nbdy);
045            return super.findLabelPlacement(path, smallNb);
046        }
047    }
048
049    @Override
050    public PositionForAreaStrategy withAddedOffset(Point2D addToOffset) {
051        if (Math.abs(addToOffset.getX()) < 1e-5 && Math.abs(addToOffset.getY()) < 1e-5) {
052            return this;
053        } else {
054            return new PartiallyInsideAreaStrategy(offsetX + addToOffset.getX(), offsetY - addToOffset.getY());
055        }
056    }
057
058    @Override
059    public String toString() {
060        return "PartiallyInsideAreaStrategy [offsetX=" + offsetX + ", offsetY=" + offsetY + "]";
061    }
062}