Skip to content

Commit

Permalink
GEOS-7020: fixed VectorRenderingLayerIdentifier bounds / size calcula…
Browse files Browse the repository at this point in the history
…tion to have a more precise scalefactor
  • Loading branch information
mbarto committed May 14, 2015
1 parent 6db6bdb commit eb9ae1e
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 35 deletions.
Expand Up @@ -38,6 +38,7 @@
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;
Expand Down Expand Up @@ -170,8 +171,8 @@ public List<FeatureCollection> identify(FeatureInfoRequestParameters params,
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
Expand All @@ -194,39 +195,7 @@ public List<FeatureCollection> identify(FeatureInfoRequestParameters params,
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();
Expand All @@ -236,6 +205,43 @@ protected void onBeforeRender(StreamingRenderer renderer) {
}
}

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"));
Expand Down
Expand Up @@ -2,19 +2,46 @@

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 {

Expand Down Expand Up @@ -253,4 +280,89 @@ public void testPureLabelPolygon() throws Exception {
// 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);
}
}

0 comments on commit eb9ae1e

Please sign in to comment.