/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2013-2016, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.styling.visitor; import java.util.HashMap; import java.util.Map; import javax.measure.converter.UnitConverter; import javax.measure.quantity.Length; import javax.measure.unit.NonSI; import javax.measure.unit.SI; import javax.measure.unit.Unit; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.Literal; /** * Helper class that allows rescaling to pixels numbers that might carry a unit specification along * with them, handling the case where real world units should not be rescaled (dpi rescaling) as * well as the simpler case where everything should be rescaled (uom rescaling) */ enum RescalingMode { /** * Rescales the values and maintains the units */ KeepUnits { @Override public String rescaleToStringInternal(double scaleFactor, Measure measure) { double rescaled = measure.value * scaleFactor; String rescaledString; if (rescaled == (int) rescaled) { rescaledString = String.valueOf((int) rescaled); } else { rescaledString = String.valueOf(rescaled); } if (measure.isPixelInPixelDefault()) { return rescaledString; } else { return rescaledString + UNIT_SYMBOLS.get(measure.uom); } } }, /** * Only rescales pixel values */ Pixels { @Override public String rescaleToStringInternal(double scaleFactor, Measure measure) { if (measure.isRealWorldUnit()) { if(measure.isRealWorldUnitInPixelDefault()){ return String.valueOf(measure.value) + UNIT_SYMBOLS.get(measure.uom); }else{ return String.valueOf(measure.value); } } else { return String.valueOf(measure.value * scaleFactor); } } @Override public Expression rescaleToExpression(Expression scaleFactor, Measure measure) { if (measure.isRealWorldUnit()) { return measure.expression; } else { return super.rescaleToExpression(scaleFactor, measure); } } }, /** * Rescales feet and meter to pixel based on the scale factor (interpreted as a scale * denominator) */ RealWorld { @Override public String rescaleToStringInternal(double scaleFactor, Measure measure) { return String.valueOf(measure.value * computeRescaleMultiplier(scaleFactor, measure.uom)); } /** * Computes a rescaling multiplier to be applied to an unscaled value. * * @param mapScale the mapScale in pixels per meter. * @param uom the unit of measure that will be used to scale. * @return the rescaling multiplier for the provided parameters. */ double computeRescaleMultiplier(double mapScale, Unit<Length> uom) { // no scaling to do if UOM is PIXEL (or null, which stands for PIXEL as well) if (uom == null || uom.equals(NonSI.PIXEL)) return 1; if (uom == SI.METER) { return mapScale; } // converts value from meters to given UOM UnitConverter converter = uom.getConverterTo(SI.METER); return converter.convert(mapScale); } }; public abstract String rescaleToStringInternal(double scaleFactor, Measure measure); public String rescaleToString(double scaleFactor, Measure measure) { if (measure.value == null) { throw new IllegalStateException( "Cannot rescale to literal, the value is a generic expression, not a static value: " + measure.expression); } return rescaleToStringInternal(scaleFactor, measure); } public Expression rescaleToExpression(Expression scaleFactor, Measure measure) { if (measure.value != null && scaleFactor instanceof Literal) { Double scale = scaleFactor.evaluate(null, Double.class); return Measure.ff.literal(rescaleToStringInternal(scale, measure)); } else { // if it's an expression, there is still a chance the expression will have, at the // end, // a unit, so we have to delay the evaluation to later return Measure.ff.function("rescaleToPixels", measure.expression, Measure.ff.literal(measure.uom), scaleFactor, Measure.ff.literal(this)); } } /** * Translates between units and their shortcuts (we can only get the full name from the unit * object */ final Map<Unit, String> UNIT_SYMBOLS = new HashMap<Unit, String>() { { put(NonSI.PIXEL, "px"); put(NonSI.FOOT, "ft"); put(SI.METER, "m"); } }; }