MapViewGeometryUtil.java
// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.streetside.utils;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.Path2D;
import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.gui.MapView;
import org.openstreetmap.josm.gui.NavigatableComponent;
import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
import org.openstreetmap.josm.plugins.streetside.StreetsideSequence;
/**
* Utility class to convert entities like {@link Bounds} and {@link StreetsideSequence} into {@link Shape}s that
* can then easily be drawn on a {@link MapView}s {@link Graphics2D}-context.
*/
public final class MapViewGeometryUtil {
private MapViewGeometryUtil() {
// Private constructor to avoid instantiation
}
/**
* Subtracts the download bounds from the rectangular bounds of the map view.
* @param mv the MapView that is used for the LatLon-to-Point-conversion and that determines
* the Bounds from which the downloaded Bounds are subtracted
* @param downloadBounds multiple {@link Bounds} objects that represent the downloaded area
* @return the difference between the {@link MapView}s bounds and the downloaded area
*/
public static Area getNonDownloadedArea(MapView mv, Iterable<Bounds> downloadBounds) {
Rectangle b = mv.getBounds();
// on some platforms viewport bounds seem to be offset from the left,
// over-grow it just to be sure
b.grow(100, 100);
Area a = new Area(b);
// now successively subtract downloaded areas
for (Bounds bounds : downloadBounds) {
Point p1 = mv.getPoint(bounds.getMin());
Point p2 = mv.getPoint(bounds.getMax());
Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min(p1.y, p2.y),
Math.abs(p2.x - p1.x), Math.abs(p2.y - p1.y));
a.subtract(new Area(r));
}
return a;
}
/**
* Converts a {@link StreetsideSequence} into a {@link Path2D} that can be drawn
* on the specified {@link NavigatableComponent}'s {@link Graphics2D}-context.
* @param nc the {@link NavigatableComponent} for which this conversion should be performed, typically a {@link MapView}
* @param seq the sequence to convert
* @return the {@link Path2D} object to which the {@link StreetsideSequence} has been converted
*/
public static Path2D getSequencePath(NavigatableComponent nc, StreetsideSequence seq) {
final Path2D.Double path = new Path2D.Double();
seq.getImages().stream().filter(StreetsideAbstractImage::isVisible).forEach(img -> {
Point p = nc.getPoint(img.getMovingLatLon());
if (path.getCurrentPoint() == null) {
path.moveTo(p.getX(), p.getY());
} else {
path.lineTo(p.getX(), p.getY());
}
});
return path;
}
}