public void setBoundsInternal(Envelope newBounds, boolean forceContainBBoxZoom) {
Envelope finalBounds = newBounds;
if (getDefaultPreferredScaleDenominators() != getPreferredScaleDenominators()
&& validState()) {
IMapDisplay mapDisplay = getRenderManagerInternal().getMapDisplay();
ReferencedEnvelope referenced;
if (newBounds instanceof ReferencedEnvelope) {
referenced = (ReferencedEnvelope) newBounds;
} else {
referenced = new ReferencedEnvelope(newBounds, getCRS());
}
double scale = ScaleUtils.calculateScaleDenominator(referenced,
mapDisplay.getDisplaySize(), mapDisplay.getDPI());
scale = ScaleUtils.calculateClosestScale(getPreferredScaleDenominators(), scale,
ScaleUtils.zoomClosenessPreference());
finalBounds = ScaleUtils.calculateBoundsFromScale(scale, mapDisplay.getDisplaySize(),
mapDisplay.getDPI(), referenced);
if (forceContainBBoxZoom && !finalBounds.contains(newBounds)) {
Iterator<Double> tail = getPreferredScaleDenominators().tailSet(scale).iterator();
// the tail will include scale because scale is one of the elements in the set. So drop that
tail.next();
Double nextLargest = tail.next();
if (nextLargest != null) {
finalBounds = ScaleUtils.calculateBoundsFromScale(nextLargest,
mapDisplay.getDisplaySize(), mapDisplay.getDPI(), referenced);
}
}
}
Envelope oldBounds = bounds == null ? new Envelope() : bounds;
if (!getBounds().isNull() && !Double.isNaN(getAspectRatio())
&& !Double.isNaN(finalBounds.getWidth()) && !Double.isNaN(finalBounds.getHeight())) {
double nRatio = finalBounds.getWidth() / finalBounds.getHeight();
if (Double.isNaN(nRatio))
nRatio = 0.0;
double dRatio = getAspectRatio();
if (validState() && Math.abs(nRatio - dRatio) > ACCURACY) {
// Returning the same newBounds box is ok, but sometimes causes an infinite loop if
// zoomToBox's calculations don't affect the size. Making this arbitrary change to
// the
// x-axis solves the problem.
final double arbitraryChange = 2 * 0.0000001;
finalBounds.init(finalBounds.getMinX() - (arbitraryChange),
(finalBounds.getMaxX() + arbitraryChange), finalBounds.getMinY(),
finalBounds.getMaxY());
zoomToBox(finalBounds);
return;
}
}
bounds = new ReferencedEnvelope(finalBounds, getCRS());
fireNotification(oldBounds);
}