Hello again folks
On the previous patches I sent regarding UOM support in 2.6.x, I did not
include a UomRescaleStyleVisitor class that we are currently using to
scale our styles/symbolizers according to the specified unit of measure.
It is currently in our own library, but if you are interested I guess it
would be nice to have in GeoTools itself. Check it out.. (attached file)
Cheers
Milton
--
Milton Jonathan
Grupo GIS e Meio Ambiente
Tecgraf/PUC-Rio
Tel: +55-21-3527-2502
package org.tecgraf.tdk.style.visitor;
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.geotools.styling.Graphic;
import org.geotools.styling.LineSymbolizer;
import org.geotools.styling.PointSymbolizer;
import org.geotools.styling.PolygonSymbolizer;
import org.geotools.styling.Stroke;
import org.geotools.styling.visitor.DuplicatingStyleVisitor;
import org.opengis.filter.expression.Expression;
/**
* Visitor used for rescaling a Style given a map scale (e.g., meters per pixel)
* and taking into consideration the Unit of Measure (UOM, e.g., SI.METER,
* NonSI.FOOT) of each symbolizer. The resulting Style's Symbolizer sizes will
* all be given in PIXELS, so that they can be directly used by a renderer that
* is unaware of units of measure or the current map scale. For example, points
* with size == 100 meters could be rescaled to 10 pixels for higher levels of
* zoom and 2 pixels for a lower level of zoom.
* <p>
* This visitor extends {...@link DuplicatingStyleVisitor} and as such yields a
* copy of the original Style. Usage is simply to call the desired visit()
* method and then call getCopy() to retrieve the result.
*
* @author milton
*/
public class UomRescaleStyleVisitor extends DuplicatingStyleVisitor
{
private double _mapScale = 1;
/**
* Constructor: requires the current mapScale to inform the window to
* viewport (world to screen) relation in order to correctly rescale sizes
* according to units of measure given in world units (e.g., SI.METER,
* NonSI.FOOT, etc).
*
* @param mapScale The specified map scale, given in pixels per meter.
*/
public UomRescaleStyleVisitor(double mapScale)
{
if (mapScale <= 0)
throw new IllegalArgumentException("mapScale must be positive.");
_mapScale = mapScale;
}
/**
* Used to rescale the provided unscaled value.
*
* @param unscaled the unscaled value.
* @param mapScale the mapScale in pixel per meter.
* @param uom the uom that will be used to scale.
* @return expr multiplied by the provided scale
*/
protected Expression rescale(Expression unscaled, double mapScale, Unit<Length> uom)
{
if (unscaled == null || unscaled.equals(Expression.NIL))
return unscaled;
double rescaled = rescale(unscaled.evaluate(null, Double.class), mapScale, uom);
return ff.literal(rescaled);
}
/**
* Used to rescale the provided unscaled value.
* <p>
* We do optimize the case where the provided expression is a literal; no
* sense doing a calculation each time if we don't have to.
*
* @param unscaled the unscaled value.
* @param mapScale the mapScale in pixel per meter.
* @param uom the uom that will be used to scale.
* @return an scaled value.
*/
protected double rescale(double unscaled, 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 unscaled;
// computes the scale value for meters given the mapScale
double scaledMetersToPixel = unscaled * mapScale;
// converts value from meters to given UOM
UnitConverter converter = uom.getConverterTo(SI.METER);
double rescaled = converter.convert(scaledMetersToPixel);
// asserts that the value is at least 1 (pixel size < 1 is invalid)
return Math.max(1, rescaled);
}
@Override
public void visit(PointSymbolizer ps)
{
super.visit(ps);
PointSymbolizer copy = (PointSymbolizer) pages.peek();
Graphic copyGraphic = copy.getGraphic();
copyGraphic.setSize(rescale(copyGraphic.getSize(), _mapScale, copy.getUnitOfMeasure()));
}
@Override
public void visit(LineSymbolizer line)
{
super.visit(line);
LineSymbolizer copy = (LineSymbolizer) pages.peek();
Stroke copyStroke = copy.getStroke();
copyStroke.setWidth(rescale(copyStroke.getWidth(), _mapScale, copy.getUnitOfMeasure()));
}
@Override
public void visit(PolygonSymbolizer poly)
{
super.visit(poly);
PolygonSymbolizer copy = (PolygonSymbolizer) pages.peek();
Stroke copyStroke = copy.getStroke();
copyStroke.setWidth(rescale(copyStroke.getWidth(), _mapScale, copy.getUnitOfMeasure()));
}
}
------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
Geotools-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/geotools-devel