Commit c8983a40 authored by Mauro Bartolomeoli's avatar Mauro Bartolomeoli
Browse files

GEOS-7020: fixed VectorRenderingLayerIdentifier bounds / size calculation to...

GEOS-7020: fixed VectorRenderingLayerIdentifier bounds / size calculation to have a more precise scalefactor
parent a16bd558
......@@ -38,6 +38,7 @@ import org.geoserver.platform.ExtensionPriority;
import org.geoserver.platform.ServiceException;
import org.geoserver.security.decorators.DecoratingFeatureSource;
import org.geoserver.wms.FeatureInfoRequestParameters;
import org.geoserver.wms.GetMapOutputFormat;
import org.geoserver.wms.GetMapRequest;
import org.geoserver.wms.MapLayerInfo;
import org.geoserver.wms.RenderingVariables;
......@@ -170,8 +171,8 @@ public class VectorRenderingLayerIdentifier extends AbstractVectorLayerIdentifie
if(radius < buffer) {
radius = buffer;
}
Envelope targetRasterSpace = new Envelope(params.getX() - radius, params.getX() + radius,
params.getY() - radius, params.getY() + radius);
Envelope targetRasterSpace = new Envelope(params.getX() - radius - 0.5, params.getX() + radius + 0.5,
params.getY() - radius - 0.5, params.getY() + radius + 0.5);
Envelope targetModelSpace = JTS.transform(targetRasterSpace, new AffineTransform2D(screenToWorld));
// prepare the image we are going to check rendering against
......@@ -194,39 +195,7 @@ public class VectorRenderingLayerIdentifier extends AbstractVectorLayerIdentifie
mc.setMapHeight(paintAreaSize);
// and now run the rendering _almost_ like a GetMap
RenderedImageMapOutputFormat rim = new RenderedImageMapOutputFormat(wms) {
private Graphics2D graphics;
@Override
protected RenderedImage prepareImage(int width, int height, IndexColorModel palette,
boolean transparent) {
return image;
}
@Override
protected Graphics2D getGraphics(boolean transparent, Color bgColor,
RenderedImage preparedImage, Map<Key, Object> hintsMap) {
graphics = super.getGraphics(transparent, bgColor, preparedImage,
hintsMap);
return graphics;
}
@Override
protected void onBeforeRender(StreamingRenderer renderer) {
// force the renderer into serial painting mode, as we need to check what
// was painted to decide which features to include in the results
Map hints = renderer.getRendererHints();
hints.put(StreamingRenderer.OPTIMIZE_FTS_RENDERING_KEY, Boolean.FALSE);
// disable antialiasing to speed up rendering
hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
// TODO: should we disable the screenmap as well?
featureInfoListener.setGraphics(graphics);
featureInfoListener.setRenderer(renderer);
renderer.addRenderListener(featureInfoListener);
}
};
GetMapOutputFormat rim = createMapOutputFormat(image, featureInfoListener);
rim.produceMap(mc);
List<SimpleFeature> features = featureInfoListener.getFeatures();
......@@ -236,6 +205,43 @@ public class VectorRenderingLayerIdentifier extends AbstractVectorLayerIdentifie
}
}
protected GetMapOutputFormat createMapOutputFormat(final BufferedImage image,
final FeatureInfoRenderListener featureInfoListener) {
return new RenderedImageMapOutputFormat(wms) {
private Graphics2D graphics;
@Override
protected RenderedImage prepareImage(int width, int height, IndexColorModel palette,
boolean transparent) {
return image;
}
@Override
protected Graphics2D getGraphics(boolean transparent, Color bgColor,
RenderedImage preparedImage, Map<Key, Object> hintsMap) {
graphics = super.getGraphics(transparent, bgColor, preparedImage,
hintsMap);
return graphics;
}
@Override
protected void onBeforeRender(StreamingRenderer renderer) {
// force the renderer into serial painting mode, as we need to check what
// was painted to decide which features to include in the results
Map hints = renderer.getRendererHints();
hints.put(StreamingRenderer.OPTIMIZE_FTS_RENDERING_KEY, Boolean.FALSE);
// disable antialiasing to speed up rendering
hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
// TODO: should we disable the screenmap as well?
featureInfoListener.setGraphics(graphics);
featureInfoListener.setRenderer(renderer);
renderer.addRenderListener(featureInfoListener);
}
};
}
private void rescaleRules(List<Rule> rules, FeatureInfoRequestParameters params) {
Map<Object, Object> rendererParams = new HashMap<Object, Object>();
Integer requestedDpi = ((Integer) params.getGetMapRequest().getFormatOptions().get("dpi"));
......
......@@ -2,19 +2,46 @@ package org.geoserver.wms.featureinfo;
import static org.junit.Assert.assertEquals;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import javax.xml.namespace.QName;
import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.mutable.MutableDouble;
import org.geoserver.data.test.MockData;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.platform.ServiceException;
import org.geoserver.wms.FeatureInfoRequestParameters;
import org.geoserver.wms.GetFeatureInfoRequest;
import org.geoserver.wms.GetMapOutputFormat;
import org.geoserver.wms.GetMapRequest;
import org.geoserver.wms.MapLayerInfo;
import org.geoserver.wms.MapProducerCapabilities;
import org.geoserver.wms.WMSMapContent;
import org.geoserver.wms.WMSTestSupport;
import org.geoserver.wms.WebMap;
import org.geoserver.wms.featureinfo.VectorRenderingLayerIdentifier.FeatureInfoRenderListener;
import org.geoserver.wms.map.AbstractMapOutputFormat;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.renderer.lite.RendererUtilities;
import org.junit.After;
import org.junit.Test;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.operation.TransformException;
import com.google.common.util.concurrent.AtomicDouble;
import com.vividsolutions.jts.geom.Envelope;
public class RenderingBasedFeatureInfoTest extends WMSTestSupport {
......@@ -253,4 +280,89 @@ public class RenderingBasedFeatureInfoTest extends WMSTestSupport {
// print(result);
assertEquals(1, result.getJSONArray("features").size());
}
/**
* Tests GEOS-7020: imprecise scale calculation in StreamingRenderer
* with VectorRenderingLayerIdentifier, due to 1 pixel missing
* in map size.
*
* @throws Exception
*/
@Test
public void testCalculatedScale() throws Exception {
int mapWidth = 1000;
int mapHeight = 500;
Envelope mapbbox = new Envelope(-2, 2, -1, 1);
ReferencedEnvelope mapEnvelope = new ReferencedEnvelope(mapbbox,
DefaultGeographicCRS.WGS84);
final HashMap<String, String> hints = new HashMap<String, String>();
double originalScale = RendererUtilities.calculateScale(mapEnvelope, mapWidth, mapHeight, hints);
double originalOGCScale = RendererUtilities.calculateOGCScale(mapEnvelope, mapWidth, hints);
final MutableDouble calculatedScale = new MutableDouble(0.0);
final MutableDouble calculatedOGCScale = new MutableDouble(0.0);
VectorRenderingLayerIdentifier vrli = new VectorRenderingLayerIdentifier(getWMS(), null) {
@Override
protected GetMapOutputFormat createMapOutputFormat(BufferedImage image,
FeatureInfoRenderListener featureInfoListener) {
return new AbstractMapOutputFormat("image/png", new String[] { "png" }) {
@Override
public WebMap produceMap(WMSMapContent mapContent) throws ServiceException,
IOException {
// let's capture mapContent for identify purpose, so
// that we can store the scale(s), to be verified later
try {
ReferencedEnvelope referencedEnvelope = new ReferencedEnvelope(mapContent.getViewport().getBounds(),
DefaultGeographicCRS.WGS84);
calculatedScale.setValue(RendererUtilities.calculateScale(
referencedEnvelope, mapContent.getMapWidth(),
mapContent.getMapHeight(), hints));
calculatedOGCScale.setValue(RendererUtilities.calculateOGCScale(
referencedEnvelope, mapContent.getMapWidth(), hints));
} catch (TransformException e) {
throw new ServiceException(e);
} catch (FactoryException e) {
throw new ServiceException(e);
}
return null;
}
@Override
public MapProducerCapabilities getCapabilities(String format) {
return null;
}
};
}
};
GetFeatureInfoRequest request = new GetFeatureInfoRequest();
GetMapRequest getMapRequest = new GetMapRequest();
List<MapLayerInfo> layers = new ArrayList<MapLayerInfo>();
layers.add(new MapLayerInfo(getCatalog().getLayerByName(
MockData.BASIC_POLYGONS.getLocalPart())));
getMapRequest.setLayers(layers);
getMapRequest.setSRS("EPSG:4326");
getMapRequest.setBbox(mapbbox);
getMapRequest.setWidth(mapWidth);
getMapRequest.setHeight(mapHeight);
request.setGetMapRequest(getMapRequest);
request.setQueryLayers(layers);
FeatureInfoRequestParameters params = new FeatureInfoRequestParameters(request);
vrli.identify(params, 10);
// 1% of error tolerance
assertEquals(originalScale, calculatedScale.doubleValue(), originalScale * 0.01);
assertEquals(originalOGCScale, calculatedOGCScale.doubleValue(), originalScale * 0.01);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment