Permalink
Browse files

fixed GEOT-4161 (UOM based symbolizers should not be affected by DPI …

…rescaling)
  • Loading branch information...
1 parent c5d1e9c commit b504d8f5242bb1639ebb777dbb7660215dfb7876 @svzdvd svzdvd committed Oct 25, 2012
@@ -0,0 +1,154 @@
+package org.geotools.styling.visitor;
+
+import java.util.Map;
+
+import javax.measure.quantity.Length;
+import javax.measure.unit.NonSI;
+import javax.measure.unit.Unit;
+
+import org.geotools.styling.LineSymbolizer;
+import org.geotools.styling.PointSymbolizer;
+import org.geotools.styling.PolygonSymbolizer;
+import org.geotools.styling.RasterSymbolizer;
+import org.geotools.styling.Symbolizer;
+import org.geotools.styling.TextSymbolizer;
+import org.opengis.filter.FilterFactory2;
+import org.opengis.filter.expression.Expression;
+
+
+/**
+ * This is a style visitor that will produce a copy of the provided
+ * style. The copy will be rescaled by a provided factor if UOM is PIXEL.
+ */
+public class DpiRescaleStyleVisitor extends RescaleStyleVisitor {
+
+ private boolean rescaling = true;
+
+
+ public DpiRescaleStyleVisitor(double scale) {
+ super(scale);
+ }
+
+ public DpiRescaleStyleVisitor(Expression scale) {
+ super(scale);
+ }
+
+ public DpiRescaleStyleVisitor(FilterFactory2 filterFactory, double scale) {
+ super(filterFactory, scale);
+ }
+
+ public DpiRescaleStyleVisitor(FilterFactory2 filterFactory, Expression scale) {
+ super(filterFactory, scale);
+ }
+
+
+ @Override
+ protected Expression rescale(Expression expr) {
+ if (rescaling) {
+ return super.rescale(expr);
+ } else {
+ return expr;
+ }
+ }
+
+ @Override
+ float[] rescale(float[] values) {
+ if (rescaling) {
+ return super.rescale(values);
+ } else {
+ return values;
+ }
+ }
+
+ @Override
+ protected void rescaleOption(Map<String, String> options, String key, double defaultValue) {
+ if (rescaling) {
+ super.rescaleOption(options, key, defaultValue);
+ } else {
+ if (options.get(key) == null && defaultValue != 0) {
+ options.put(key, String.valueOf(defaultValue));
+ }
+ }
+ }
+
+ @Override
+ protected void rescaleOption(Map<String, String> options, String key, int defaultValue) {
+ if (rescaling) {
+ super.rescaleOption(options, key, defaultValue);
+ } else {
+ if (options.get(key) == null && defaultValue != 0) {
+ options.put(key, String.valueOf(defaultValue));
+ }
+ }
+ }
+
+ private void setRescaling(Symbolizer symbolizer) {
+ // scaling to do only if UOM is PIXEL (or null, which stands for PIXEL as well)
+ Unit<Length> uom = symbolizer.getUnitOfMeasure();
+ setRescaling(uom == null || uom.equals(NonSI.PIXEL));
+ }
+
+ private void setRescaling(boolean rescaling) {
+ this.rescaling = rescaling;
+ }
+
+ @Override
+ public void visit(Symbolizer sym) {
+ setRescaling(sym);
+ try {
+ super.visit(sym);
+ } finally {
+ setRescaling(true);
+ }
+ }
+
+ @Override
+ public void visit(PointSymbolizer sym) {
+ setRescaling(sym);
+ try {
+ super.visit(sym);
+ } finally {
+ setRescaling(true);
+ }
+ }
+
+ @Override
+ public void visit(LineSymbolizer sym) {
+ setRescaling(sym);
+ try {
+ super.visit(sym);
+ } finally {
+ setRescaling(true);
+ }
+ }
+
+ @Override
+ public void visit(PolygonSymbolizer sym) {
+ setRescaling(sym);
+ try {
+ super.visit(sym);
+ } finally {
+ setRescaling(true);
+ }
+ }
+
+ @Override
+ public void visit(TextSymbolizer sym) {
+ setRescaling(sym);
+ try {
+ super.visit(sym);
+ } finally {
+ setRescaling(true);
+ }
+ }
+
+ @Override
+ public void visit(RasterSymbolizer sym) {
+ setRescaling(sym);
+ try {
+ super.visit(sym);
+ } finally {
+ setRescaling(true);
+ }
+ }
+}
@@ -85,6 +85,7 @@
import org.geotools.geometry.jts.LiteCoordinateSequenceFactory;
import org.geotools.geometry.jts.LiteShape2;
import org.geotools.geometry.jts.ReferencedEnvelope;
+import org.geotools.map.DirectLayer;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.map.MapContext;
@@ -115,11 +116,10 @@
import org.geotools.styling.RuleImpl;
import org.geotools.styling.Style;
import org.geotools.styling.StyleAttributeExtractor;
-import org.geotools.styling.StyleFactory;
import org.geotools.styling.Symbolizer;
import org.geotools.styling.TextSymbolizer;
+import org.geotools.styling.visitor.DpiRescaleStyleVisitor;
import org.geotools.styling.visitor.DuplicatingStyleVisitor;
-import org.geotools.styling.visitor.RescaleStyleVisitor;
import org.geotools.styling.visitor.UomRescaleStyleVisitor;
import org.geotools.util.NumberRange;
import org.opengis.coverage.processing.Operation;
@@ -151,7 +151,6 @@
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
-import org.geotools.map.DirectLayer;
/**
* A streaming implementation of the GTRenderer interface.
@@ -270,7 +269,7 @@
* The ratio required to scale the features to be rendered so that they fit
* into the output space.
*/
- private double scaleDenominator;
+ protected double scaleDenominator;
/** Maximum displacement for generalization during rendering */
private double generalizationDistance = 0.8;
@@ -2312,23 +2311,23 @@ Query adaptQuery(Query query, FeatureType targetSchema, FeatureType originalSche
* @param lfts
*/
void applyUnitRescale(final ArrayList<LiteFeatureTypeStyle> lfts) {
- // apply UOM rescaling
- double pixelsPerMeters = RendererUtilities.calculatePixelsPerMeterRatio(scaleDenominator, rendererHints);
- UomRescaleStyleVisitor rescaleVisitor = new UomRescaleStyleVisitor(pixelsPerMeters);
- for(LiteFeatureTypeStyle fts : lfts) {
- rescaleFeatureTypeStyle(fts, rescaleVisitor);
- }
-
// apply dpi rescale
double dpi = RendererUtilities.getDpi(getRendererHints());
double standardDpi = RendererUtilities.getDpi(Collections.emptyMap());
if(dpi != standardDpi) {
double scaleFactor = dpi / standardDpi;
- RescaleStyleVisitor dpiVisitor = new RescaleStyleVisitor(scaleFactor);
+ DpiRescaleStyleVisitor dpiVisitor = new DpiRescaleStyleVisitor(scaleFactor);
for(LiteFeatureTypeStyle fts : lfts) {
rescaleFeatureTypeStyle(fts, dpiVisitor);
}
}
+
+ // apply UOM rescaling
+ double pixelsPerMeters = RendererUtilities.calculatePixelsPerMeterRatio(scaleDenominator, rendererHints);
+ UomRescaleStyleVisitor rescaleVisitor = new UomRescaleStyleVisitor(pixelsPerMeters);
+ for(LiteFeatureTypeStyle fts : lfts) {
+ rescaleFeatureTypeStyle(fts, rescaleVisitor);
+ }
}
/**
@@ -0,0 +1,100 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2012, 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.renderer.lite;
+
+import java.awt.Graphics2D;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.Assert;
+
+import org.geotools.factory.CommonFactoryFinder;
+import org.geotools.styling.FeatureTypeStyle;
+import org.geotools.styling.LineSymbolizer;
+import org.geotools.styling.Rule;
+import org.geotools.styling.StyleFactory2;
+import org.geotools.styling.UomOgcMapping;
+import org.junit.Before;
+import org.junit.Test;
+import org.opengis.filter.FilterFactory2;
+
+
+public class UnitRescaleTest {
+
+ private StyleFactory2 sf;
+ private FilterFactory2 ff;
+
+ @Before
+ public void setUp() throws Exception {
+ sf = (StyleFactory2) CommonFactoryFinder.getStyleFactory(null);
+ ff = CommonFactoryFinder.getFilterFactory2(null);
+ }
+
+ @Test
+ public void testUOMEncodingLineSymbolizer() throws Exception {
+ LineSymbolizer lineSymbolizer = sf.createLineSymbolizer();
+ lineSymbolizer.setUnitOfMeasure(UomOgcMapping.METRE.getUnit());
+ lineSymbolizer.setStroke(sf.createStroke(ff.literal("#0000FF"), ff.literal("3")));
+
+ Rule rule = sf.createRule();
+ rule.symbolizers().add(lineSymbolizer);
+
+ Rule[] rules = new Rule[] { rule };
+ FeatureTypeStyle featureTypeStyle = sf.createFeatureTypeStyle(rules);
+
+ List<FeatureTypeStyle> featureTypeStyles = new ArrayList<FeatureTypeStyle>();
+ featureTypeStyles.add(featureTypeStyle);
+
+ double dpi90 = 25.4 / 0.28;
+ double widthAtDpi90 = 10714.286;
+ Assert.assertEquals(widthAtDpi90, getStrokeWidth(featureTypeStyles, rules, dpi90), 0.1);
+ Assert.assertEquals(widthAtDpi90 * 2, getStrokeWidth(featureTypeStyles, rules, dpi90 * 2), 0.5);
+ Assert.assertEquals(widthAtDpi90 * 3, getStrokeWidth(featureTypeStyles, rules, dpi90 * 3), 0.5);
+ Assert.assertEquals(widthAtDpi90 * 4, getStrokeWidth(featureTypeStyles, rules, dpi90 * 4), 0.5);
+ Assert.assertEquals(widthAtDpi90 * 5, getStrokeWidth(featureTypeStyles, rules, dpi90 * 5), 0.5);
+ }
+
+ private double getStrokeWidth(List<FeatureTypeStyle> featureTypeStyles, Rule[] rules, double dpi) {
+ ArrayList<LiteFeatureTypeStyle> lfts = new ArrayList<LiteFeatureTypeStyle>();
+ for (FeatureTypeStyle fts : featureTypeStyles) {
+ List<Rule> ruleList = new ArrayList<Rule>(Arrays.asList(rules));
+ List<Rule> elseRuleList = new ArrayList<Rule>();
+ LiteFeatureTypeStyle s = new LiteFeatureTypeStyle(null, ruleList, elseRuleList, fts.getTransformation());
+ lfts.add(s);
+ }
+
+ Map hints = new HashMap();
+ hints.put("dpi", new Double(dpi));
+
+ StreamingRenderer renderer = new StreamingRenderer();
+ renderer.scaleDenominator = 1;
+ renderer.setRendererHints(hints);
+ renderer.applyUnitRescale(lfts);
+
+ for (LiteFeatureTypeStyle s : lfts) {
+ Rule r = s.ruleList[0];
+ LineSymbolizer rescaledLineSymbolizer = (LineSymbolizer) r.getSymbolizers()[0];
+ return rescaledLineSymbolizer.getStroke().getWidth().evaluate(null, Double.class);
+ }
+
+ // this should not happen
+ return -1;
+ }
+}

0 comments on commit b504d8f

Please sign in to comment.