/*******************************************************************************
* Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com)
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v3
* which accompanies this distribution, and is available at http://www.gnu.org/licenses/lgpl.txt
******************************************************************************/
package com.opendoorlogistics.core.gis.map;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.util.Set;
import com.opendoorlogistics.codefromweb.jxmapviewer2.ExpiringOSMLocalResponseCache;
import com.opendoorlogistics.codefromweb.jxmapviewer2.fork.swingx.mapviewer.GeoPosition;
import com.opendoorlogistics.codefromweb.jxmapviewer2.fork.swingx.mapviewer.TileFactoryInfo;
import com.opendoorlogistics.codefromweb.jxmapviewer2.fork.swingx.mapviewer.util.GeoUtil;
import com.opendoorlogistics.core.utils.Pair;
final public class JXMapUtils {
private JXMapUtils(){}
/**
* Find the zoom which would fit in the range of input lat and longs
*
* @param control
* @param positions
* @param imageSize
* @param maxFraction
* @return Pair where first is the best zoom level and second is the tightness of fit (0= taking up no space, 1 = taking up all space).
*/
public static Pair<Integer, Double> getBestFitZoom(TileFactoryInfo info, Set<GeoPosition> positions, int imageWidth, int imageHeight, double maxFraction) {
// set to maximum zoomed out
final double targetWidth = imageWidth * maxFraction;
final double targetHeight= imageHeight * maxFraction;
int zoom = info.getMaximumZoomLevel();
int bestZoom = zoom;
double bestFit=0;
if (positions.size() > 0) {
// set to central position initially
Rectangle2D bounds = generateBoundingRect(info, positions, zoom);
// repeatedly zoom in until we find the first zoom level where either the width or height
// of the points takes up more than the max fraction of the viewport
while (zoom >= info.getMinimumZoomLevel() && positions.size() > 1) {
// is this zoom still OK?
bounds = generateBoundingRect(info, positions, zoom);
if (bounds.getWidth() < targetWidth && bounds.getHeight() < targetHeight) {
// zoom is still good
bestZoom = zoom;
// calculate 'goodness of fit', where 1 is perfect, 0 is crap..
double horizFit = bounds.getWidth() / targetWidth;
double vertFit = bounds.getHeight()/ targetHeight;
bestFit= Math.max(horizFit, vertFit);
} else {
break;
}
zoom--;
}
}
return new Pair<Integer, Double>(bestZoom, bestFit);
}
public static Rectangle2D generateBoundingRect(TileFactoryInfo info, Set<GeoPosition> positions, int zoom) {
Rectangle2D rect = null;
for (GeoPosition pos : positions) {
Point2D pnt = GeoUtil.getBitmapCoordinate(pos, zoom, info);
if (rect == null) {
rect = new Rectangle2D.Double(pnt.getX(), pnt.getY(), 0, 0);
} else {
rect.add(pnt);
}
}
return rect;
}
}