All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mapfish.print.attribute.map.MapBounds Maven / Gradle / Ivy

package org.mapfish.print.attribute.map;

import com.vividsolutions.jts.geom.Coordinate;

import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.referencing.GeodeticCalculator;
import org.mapfish.print.map.DistanceUnit;
import org.mapfish.print.map.Scale;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.Rectangle;

/**
 * Class Represents the bounds of the map in some way.  The implementations will represent the as a bbox or as a center and scale.
 * Created by Jesse on 3/26/14.
 */
public abstract class MapBounds {
    private final CoordinateReferenceSystem projection;
    private static final Logger LOGGER = LoggerFactory.getLogger(MapBounds.class);

    /**
     * Constructor.
     *
     * @param projection the projection these bounds are defined in.
     */
    protected MapBounds(final CoordinateReferenceSystem projection) {
        this.projection = projection;
    }

    /**
     * Create a {@link org.geotools.geometry.jts.ReferencedEnvelope} representing the bounds.
     * 

* * @param paintArea the size of the map that will be drawn. * @param dpi the dpi of the map */ public abstract ReferencedEnvelope toReferencedEnvelope(Rectangle paintArea, double dpi); /** * Create a {@link org.geotools.geometry.jts.ReferencedEnvelope} representing the bounds. *

* * @param paintArea the size of the map that will be drawn. */ public abstract MapBounds adjustedEnvelope(Rectangle paintArea); /** * Get the projection these bounds are calculated in. */ public final CoordinateReferenceSystem getProjection() { return this.projection; } /** * Adjust these bounds so that they are adjusted to the nearest scale in the provided set of scales. * * The center should remain the same and the scale should be adjusted * * @param zoomLevels the list of Zoom Levels * @param tolerance the tolerance to use when considering if two values are equal. For example if 12.0 == 12.001. * The tolerance is a percentage * @param zoomLevelSnapStrategy the strategy to use for snapping to the nearest zoom level. * @param geodetic snap to geodetic scales. * @param paintArea the paint area of the map. * @param dpi the dpi of the map */ public abstract MapBounds adjustBoundsToNearestScale( final ZoomLevels zoomLevels, final double tolerance, final ZoomLevelSnapStrategy zoomLevelSnapStrategy, final boolean geodetic, final Rectangle paintArea, final double dpi); /** * Calculate and return the scale of the map bounds. * * @param paintArea the paint area of the map. * @param dpi the dpi of the map */ public abstract Scale getScaleDenominator(final Rectangle paintArea, final double dpi); /** * Calculate and return the geodetic scale of the map bounds. * * @param paintArea the paint area of the map. * @param dpi the dpi of the map */ public final Scale getGeodeticScaleDenominator(final Rectangle paintArea, final double dpi) { DistanceUnit projUnit = DistanceUnit.fromProjection(getProjection()); if (projUnit == DistanceUnit.DEGREES) { return getScaleDenominator(paintArea, dpi); } try { final ReferencedEnvelope bboxAdjustedToScreen = toReferencedEnvelope(paintArea, dpi); final GeodeticCalculator calculator = new GeodeticCalculator(getProjection()); final double centerY = bboxAdjustedToScreen.centre().y; final MathTransform transform = CRS.findMathTransform(getProjection(), GenericMapAttribute.parseProjection("EPSG:4326", true)); final Coordinate start = JTS.transform(new Coordinate(bboxAdjustedToScreen.getMinX(), centerY), null, transform); final Coordinate end = JTS.transform(new Coordinate(bboxAdjustedToScreen.getMaxX(), centerY), null, transform); calculator.setStartingGeographicPoint(start.x, start.y); calculator.setDestinationGeographicPoint(end.x, end.y); final double geoWidthInEllipsoidUnits = calculator.getOrthodromicDistance(); final DistanceUnit ellipsoidUnit = DistanceUnit.fromString(calculator.getEllipsoid().getAxisUnit().toString()); final double geoWidthInInches = ellipsoidUnit.convertTo(geoWidthInEllipsoidUnits, DistanceUnit.IN); return new Scale(geoWidthInInches * (dpi / paintArea.getWidth())); } catch (FactoryException e) { LOGGER.error("Unable to do the geodetic calculation on the scale", e); } catch (TransformException e) { LOGGER.error("Unable to do the geodetic calculation on the scale", e); } // fall back return getScaleDenominator(paintArea, dpi); } /** * In case a rotation is used for the map, the bounds have to be adjusted so that all * visible parts are rendered. * * @param rotation The rotation of the map in radians. * @return Bounds adjusted to the map rotation. */ public abstract MapBounds adjustBoundsToRotation(final double rotation); /** * Zooms-out the bounds by the given factor. * * @param factor The zoom factor. * @return Bounds adjusted to the zoom factor. */ public abstract MapBounds zoomOut(final double factor); /** * Zoom to the given scale. * * @param scale The new scale. * @return Bounds adjusted to the scale. */ public abstract MapBounds zoomToScale(final double scale); // CHECKSTYLE:OFF @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } MapBounds mapBounds = (MapBounds) o; if (!projection.equals(mapBounds.projection)) { return false; } return true; } @Override public int hashCode() { return projection.hashCode(); } // CHECKSTYLE:ON }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy