@Test public void testInterpolationByLayer() throws Exception { StreamingRenderer sr = new StreamingRenderer(); Layer layer = new FeatureLayer(createLineCollection(), createLineStyle()); // default is nearest neighbor assertEquals( sr.getRenderingInterpolation(layer), Interpolation.getInstance(Interpolation.INTERP_NEAREST)); // test all possible values layer .getUserData() .put( StreamingRenderer.BYLAYER_INTERPOLATION, Interpolation.getInstance(Interpolation.INTERP_BICUBIC)); assertEquals( sr.getRenderingInterpolation(layer), Interpolation.getInstance(Interpolation.INTERP_BICUBIC)); layer .getUserData() .put( StreamingRenderer.BYLAYER_INTERPOLATION, Interpolation.getInstance(Interpolation.INTERP_BILINEAR)); assertEquals( sr.getRenderingInterpolation(layer), Interpolation.getInstance(Interpolation.INTERP_BILINEAR)); layer .getUserData() .put( StreamingRenderer.BYLAYER_INTERPOLATION, Interpolation.getInstance(Interpolation.INTERP_NEAREST)); assertEquals( sr.getRenderingInterpolation(layer), Interpolation.getInstance(Interpolation.INTERP_NEAREST)); }
/** * Test that point features are rendered at the expected image coordinates when the map is * rotated. StreamingRenderer * * @throws Exception */ @Test public void testRotatedTransform() throws Exception { // If we rotate the world rectangle + 90 degrees around (0,0), we get the screen rectangle final Rectangle screen = new Rectangle(0, 0, 100, 50); final Envelope world = new Envelope(0, 50, 0, -100); final AffineTransform worldToScreen = AffineTransform.getRotateInstance(Math.toRadians(90), 0, 0); DefaultFeatureCollection fc = new DefaultFeatureCollection(); fc.add(createPoint(0, 0)); fc.add(createPoint(world.getMaxX(), world.getMinY())); MapContext mapContext = new DefaultMapContext(DefaultGeographicCRS.WGS84); mapContext.addLayer((FeatureCollection) fc, createPointStyle()); BufferedImage image = new BufferedImage(screen.width, screen.height, BufferedImage.TYPE_4BYTE_ABGR); final StreamingRenderer sr = new StreamingRenderer(); sr.setContext(mapContext); sr.paint(image.createGraphics(), screen, worldToScreen); assertTrue("Pixel should be drawn at 0,0 ", image.getRGB(0, 0) != 0); assertTrue( "Pixel should not be drawn in image centre ", image.getRGB(screen.width / 2, screen.height / 2) == 0); assertTrue( "Pixel should be drawn at image max corner ", image.getRGB(screen.width - 1, screen.height - 1) != 0); }
public void testSkipProjectionErrors() throws Exception { // build map context MapContext mapContext = new DefaultMapContext(DefaultGeographicCRS.WGS84); mapContext.addLayer(createLineCollection(), createLineStyle()); // build projected envelope to work with (small one around the area of // validity of utm zone 1, which being a Gauss projection is a vertical // slice parallel to the central meridian, -177°) ReferencedEnvelope reWgs = new ReferencedEnvelope(new Envelope(-180, -170, 20, 40), DefaultGeographicCRS.WGS84); CoordinateReferenceSystem utm1N = CRS.decode("EPSG:32601"); System.out.println(CRS.getGeographicBoundingBox(utm1N)); ReferencedEnvelope reUtm = reWgs.transform(utm1N, true); BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_4BYTE_ABGR); // setup the renderer and listen for errors StreamingRenderer sr = new StreamingRenderer(); sr.setRendererHints(Collections.singletonMap(sr.OPTIMIZED_DATA_LOADING_KEY, Boolean.FALSE)); sr.setContext(mapContext); sr.addRenderListener( new RenderListener() { public void featureRenderer(SimpleFeature feature) {} public void errorOccurred(Exception e) { e.printStackTrace(); errors++; } }); errors = 0; sr.paint((Graphics2D) image.getGraphics(), new Rectangle(200, 200), reUtm); // we should get two errors since there are two features that cannot be // projected but the renderer itself should not throw exceptions assertEquals(2, errors); }
/* * https://osgeo-org.atlassian.net/browse/GEOT-5287 */ @Test public void testEmptyGeometryRendering() throws Exception { MapContent mc = new MapContent(); /* * We simulate reading empty geometries with this properties and mocking the capability to * filter, so that no filter layer is installed over our data and the empty geometry reaches * rendering code. These geometries are in EPSG:32717 because the 0,0 coordinate is in the * pole. */ File dir = new File(TestData.getResource(this, "empty-geom-rendering.properties").toURI()); PropertyDataStore dataStore = new PropertyDataStore(dir.getParentFile()) { @Override protected ContentFeatureSource createFeatureSource(ContentEntry entry) throws IOException { return new PropertyFeatureSource(entry, Query.ALL) { @Override protected boolean canFilter() { return true; } }; } }; /* * Set up the rendering of previous empty geometry */ StyleBuilder sb = new StyleBuilder(); Style style = sb.createStyle(sb.createPolygonSymbolizer()); Layer layer = new FeatureLayer(dataStore.getFeatureSource("empty-geom-rendering"), style); mc.addLayer(layer); StreamingRenderer sr = new StreamingRenderer(); sr.setMapContent(mc); BufferedImage img = new BufferedImage(40, 40, BufferedImage.TYPE_INT_ARGB); Graphics2D graphics = img.createGraphics(); Rectangle paintArea = new Rectangle(40, 40); // An EPSG:8357 extent on the EPSG:32717 area of application. double minx = -8929252.1; double maxx = -8708634.6; double miny = -491855.7; double maxy = -271204.3; ReferencedEnvelope referencedEnvelope = new ReferencedEnvelope( new Rectangle2D.Double(minx, miny, maxx - minx, maxy - miny), CRS.decode("EPSG:3857")); sr.addRenderListener( new RenderListener() { public void featureRenderer(SimpleFeature feature) {} public void errorOccurred(Exception e) { errors++; } }); errors = 0; sr.paint(graphics, paintArea, referencedEnvelope); assertTrue(errors == 0); }
@Test public void testDrawIntepolation() throws Exception { MapContent mc = new MapContent(); ReferencedEnvelope reWgs = new ReferencedEnvelope(new Envelope(-180, 180, -90, 90), DefaultGeographicCRS.WGS84); BufferedImage testImage = new BufferedImage(200, 200, BufferedImage.TYPE_4BYTE_ABGR); GridCoverage2D testCoverage = new GridCoverageFactory().create("test", testImage, reWgs); GridCoverage2D coverage = new GridCoverage2D("test", testCoverage); // mocking a GridCoverageReader to wrap the testing coverage GridCoverage2DReader gridCoverageReader = Mockito.mock(GridCoverage2DReader.class); Mockito.when(gridCoverageReader.getOriginalEnvelope()).thenReturn(new GeneralEnvelope(reWgs)); Mockito.when(gridCoverageReader.getCoordinateReferenceSystem()) .thenReturn(DefaultGeographicCRS.WGS84); Mockito.when(gridCoverageReader.read(Mockito.any(GeneralParameterValue[].class))) .thenReturn(coverage); Layer layer = new FeatureLayer( FeatureUtilities.wrapGridCoverageReader( gridCoverageReader, new GeneralParameterValue[] {}), createRasterStyle()); layer .getUserData() .put( StreamingRenderer.BYLAYER_INTERPOLATION, Interpolation.getInstance(Interpolation.INTERP_BICUBIC)); mc.addLayer(layer); BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_4BYTE_ABGR); StreamingRenderer sr = new StreamingRenderer(); sr.setMapContent(mc); Graphics2D graphics = (Graphics2D) image.getGraphics(); sr.paint(graphics, new Rectangle(200, 200), reWgs); // test right interpolation hint is set on Graphics2D assertEquals( graphics.getRenderingHint(JAI.KEY_INTERPOLATION), Interpolation.getInstance(Interpolation.INTERP_BICUBIC)); layer .getUserData() .put( StreamingRenderer.BYLAYER_INTERPOLATION, Interpolation.getInstance(Interpolation.INTERP_NEAREST)); sr.paint(graphics, new Rectangle(200, 200), reWgs); // test right interpolation hint is set on Graphics2D assertEquals( graphics.getRenderingHint(JAI.KEY_INTERPOLATION), Interpolation.getInstance(Interpolation.INTERP_NEAREST)); }
@Test public void testEventAfterDrawing() throws Exception { // build map context MapContent mc = new MapContent(); mc.addLayer(new FeatureLayer(createLineCollection(), createLineStyle())); // build projected envelope to work with (small one around the area of // validity of utm zone 1, which being a Gauss projection is a vertical // slice parallel to the central meridian, -177°) ReferencedEnvelope reWgs = new ReferencedEnvelope(new Envelope(-180, -170, 20, 40), DefaultGeographicCRS.WGS84); CoordinateReferenceSystem utm1N = CRS.decode("EPSG:32601"); ReferencedEnvelope reUtm = reWgs.transform(utm1N, true); BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_4BYTE_ABGR); // setup the renderer and listen for errors final AtomicInteger commandsCount = new AtomicInteger(0); final BlockingQueue<RenderingRequest> queue = new ArrayBlockingQueue<RenderingRequest>(10) { @Override public void put(RenderingRequest e) throws InterruptedException { commandsCount.incrementAndGet(); super.put(e); } }; StreamingRenderer sr = new StreamingRenderer() { @Override protected BlockingQueue<RenderingRequest> getRequestsQueue() { return queue; } }; sr.setMapContent(mc); sr.addRenderListener( new RenderListener() { public void featureRenderer(SimpleFeature feature) { assertTrue(commandsCount.get() > 0); features++; } public void errorOccurred(Exception e) { errors++; } }); errors = 0; features = 0; sr.paint((Graphics2D) image.getGraphics(), new Rectangle(200, 200), reUtm); // we should get errors since there are two features that cannot be // projected but the renderer itself should not throw exceptions assertTrue(errors > 0); }
@Override protected void setUp() throws Exception { // setup data File property = new File(TestData.getResource(this, "diaglines.properties").toURI()); PropertyDataStore ds = new PropertyDataStore(property.getParentFile()); fs = ds.getFeatureSource("diaglines"); bounds = new ReferencedEnvelope(0, 10, 0, 10, DefaultGeographicCRS.WGS84); renderer = new StreamingRenderer(); Map rendererParams = new HashMap(); LabelCacheImpl labelCache = new LabelCacheImpl(); rendererParams.put(StreamingRenderer.LABEL_CACHE_KEY, labelCache); renderer.setRendererHints(rendererParams); renderer.setJava2DHints(new RenderingHints(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON)); // System.setProperty("org.geotools.test.interactive", "true"); }
@Test public void testRepeatedEnvelopeExpansion() throws Exception { final List<Filter> filters = new ArrayList<Filter>(); SimpleFeatureSource testSource = new CollectionFeatureSource(createLineCollection()) { @Override public SimpleFeatureCollection getFeatures(Query query) { filters.add(query.getFilter()); return super.getFeatures(query); } }; StyleBuilder sb = new StyleBuilder(); Style style20 = sb.createStyle(sb.createLineSymbolizer(20)); Style style10 = sb.createStyle(sb.createLineSymbolizer(10)); MapContent mc = new MapContent(); mc.addLayer(new FeatureLayer(testSource, style20)); mc.addLayer(new FeatureLayer(testSource, style10)); StreamingRenderer sr = new StreamingRenderer(); sr.setMapContent(mc); BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_3BYTE_BGR); Graphics2D graphics = bi.createGraphics(); sr.paint( graphics, new Rectangle(0, 0, 100, 100), new ReferencedEnvelope(0, 100, 0, 100, DefaultGeographicCRS.WGS84)); graphics.dispose(); System.out.println(filters); assertEquals(2, filters.size()); Filter f1 = filters.get(0); assertTrue(f1 instanceof BBOX); BoundingBox bbox1 = ((BBOX) f1).getBounds(); ReferencedEnvelope expected = new ReferencedEnvelope(-11, 111, -11, 111, DefaultGeographicCRS.WGS84); assertEquals(expected, bbox1); Filter f2 = filters.get(1); assertTrue(f2 instanceof BBOX); BoundingBox bbox2 = ((BBOX) f2).getBounds(); assertEquals(new ReferencedEnvelope(-6, 106, -6, 106, DefaultGeographicCRS.WGS84), bbox2); }
/** * Test that we don't have the geometry added twice by StreamingRenderer#findStyleAttributes when * geofence is filtering a layer. * * @throws Exception */ @Test public void testFindLineStyleAttributeWithAddedFilter() throws Exception { final List<Filter> filters = new ArrayList<Filter>(); SimpleFeatureSource testSource = new CollectionFeatureSource(createLineCollection()) { @Override public SimpleFeatureCollection getFeatures(Query query) { filters.add(query.getFilter()); return super.getFeatures(query); } }; Style style = createPointStyle(); MapContent mc = new MapContent(); FeatureLayer layer = new FeatureLayer(testSource, style); mc.addLayer(layer); StreamingRenderer sr = new StreamingRenderer(); sr.setMapContent(mc); ReferencedEnvelope envelope = new ReferencedEnvelope(0, 100, 0, 100, DefaultGeographicCRS.WGS84); // simulate geofence adding a bbox BBOX bbox = StreamingRenderer.filterFactory.bbox("", 30, 60, 30, 60, "WGS84"); StyleFactoryImpl sf = new StyleFactoryImpl(); Rule bboxRule = sf.createRule( new Symbolizer[0], new DescriptionImpl(), new Graphic[0], "bbox", bbox, false, 1e12, 0); style.featureTypeStyles().get(0).rules().add(bboxRule); BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_3BYTE_BGR); Graphics2D graphics = bi.createGraphics(); try { sr.paint(graphics, new Rectangle(5, 5, 7, 7), envelope); } finally { graphics.dispose(); } // must have only one bbox, not two assertEquals(1, filters.size()); assertEquals(FastBBOX.class, filters.get(0).getClass()); }
public void testLabelLineOrientation() throws Exception { Style style = RendererBaseTest.loadStyle(this, "textLineOrientation.sld"); DefaultMapContext mc = new DefaultMapContext(DefaultGeographicCRS.WGS84); mc.addLayer(fs, style); renderer.setContext(mc); RendererBaseTest.showRender("Lines with circl stroke", renderer, TIME, bounds); }
public void testPolyLabeling() throws Exception { FeatureCollection collection = createPolyFeatureCollection(); Style style = loadStyle("PolyStyle.sld"); assertNotNull(style); MapContext map = new DefaultMapContext(DefaultGeographicCRS.WGS84); map.addLayer(collection, style); StreamingRenderer renderer = new StreamingRenderer(); renderer.setContext(map); ReferencedEnvelope env = map.getLayerBounds(); int boundary = 10; env = new ReferencedEnvelope( env.getMinX() - boundary, env.getMaxX() + boundary, env.getMinY() - boundary, env.getMaxY() + boundary, null); RendererBaseTest.showRender("testPolyLabeling", renderer, timout, env); }
private void testTransformWithQuery(boolean invert) throws IOException, URISyntaxException, CQLException, NoSuchAuthorityCodeException, FactoryException, Exception { // grab the style Style style = RendererBaseTest.loadStyle( this, invert ? "attributeRename.sld" : "attributeRenameNoInvert.sld"); // grab the data File property = new File(TestData.getResource(this, "point.properties").toURI()); PropertyDataStore ds = new PropertyDataStore(property.getParentFile()); FeatureSource fs = ds.getFeatureSource("point"); // prepare a feature layer with a query and the rendering tx FeatureLayer layer = new FeatureLayer(fs, style); layer.setQuery(new Query(null, CQL.toFilter("id > 5"))); // render it MapContent mc = new MapContent(); mc.addLayer(layer); StreamingRenderer renderer = new StreamingRenderer(); final AtomicInteger counter = new AtomicInteger(); renderer.addRenderListener( new RenderListener() { @Override public void featureRenderer(SimpleFeature feature) { counter.incrementAndGet(); } @Override public void errorOccurred(Exception e) {} }); renderer.setMapContent(mc); ReferencedEnvelope re = new ReferencedEnvelope(0, 12, 0, 12, CRS.decode("EPSG:4326")); BufferedImage image = RendererBaseTest.showRender("Lines with circle stroke", renderer, TIME, re); // if everything went fine we'll have a single red dot in the middle, and we rendered // just one feature assertEquals(1, counter.get()); assertEquals(Color.RED, getPixelColor(image, image.getWidth() / 2, image.getHeight() / 2)); }
@Test public void testTransformReproject() throws Exception { // grab the style Style style = RendererBaseTest.loadStyle(this, "reproject-rt.sld"); // grab the data File property = new File(TestData.getResource(this, "point.properties").toURI()); PropertyDataStore ds = new PropertyDataStore(property.getParentFile()); FeatureSource fs = ds.getFeatureSource("point"); // prepare a feature layer with a query and the rendering tx FeatureLayer layer = new FeatureLayer(fs, style); // prepare a bbox in UTM-32N ReferencedEnvelope reWgs84 = new ReferencedEnvelope(0, 12, 0, 12, CRS.decode("EPSG:4326")); ReferencedEnvelope reUTM32N = reWgs84.transform(CRS.decode("EPSG:3857"), true); // render it MapContent mc = new MapContent(); mc.addLayer(layer); StreamingRenderer renderer = new StreamingRenderer(); final AtomicInteger counter = new AtomicInteger(); renderer.addRenderListener( new RenderListener() { @Override public void featureRenderer(SimpleFeature feature) { counter.incrementAndGet(); } @Override public void errorOccurred(Exception e) {} }); renderer.setMapContent(mc); BufferedImage image = RendererBaseTest.showRender("Lines with circle stroke", renderer, TIME, reUTM32N); // if everything went fine we rendered all the features assertEquals(10, counter.get()); assertEquals(Color.RED, getPixelColor(image, image.getWidth() / 2, image.getHeight() / 2)); }
@Test public void testTransformNullCoverage() throws Exception { Style style = RendererBaseTest.loadStyle(this, "coverageCenter.sld"); GridCoverage2DReader reader = new AbstractGridCoverage2DReader() { @Override public Format getFormat() { return null; } @Override public GridCoverage2D read(GeneralParameterValue[] parameters) throws IllegalArgumentException, IOException { // we return null on purpose, simulating a reader queried outside of its area, or // on a dimension value it does not have return null; } }; MapContent mc = new MapContent(); mc.addLayer(new GridReaderLayer(reader, style)); StreamingRenderer renderer = new StreamingRenderer(); renderer.setMapContent(mc); ReferencedEnvelope re = new ReferencedEnvelope(-70, 70, -160, 160, CRS.decode("EPSG:4326")); BufferedImage image = RendererBaseTest.showRender("Transformation with null input", renderer, TIME, re); // full white, no NPE double[] minimums = new ImageWorker(image).getMinimums(); assertEquals(255, minimums[0], 0d); assertEquals(255, minimums[1], 0d); assertEquals(255, minimums[2], 0d); assertEquals(255, minimums[3], 0d); }
@Test public void testTransformReprojectedGridCoverage() throws Exception { Style style = RendererBaseTest.loadStyle(this, "coverageCenter.sld"); GeoTiffReader reader = new GeoTiffReader(TestData.copy(this, "geotiff/world.tiff")); MapContent mc = new MapContent(); mc.addLayer(new GridCoverageLayer(reader.read(null), style)); StreamingRenderer renderer = new StreamingRenderer(); renderer.setMapContent(mc); ReferencedEnvelope reWgs84 = new ReferencedEnvelope(-70, 70, -160, 160, CRS.decode("EPSG:4326")); ReferencedEnvelope re = reWgs84.transform(CRS.decode("EPSG:3857"), true); BufferedImage image = RendererBaseTest.showRender("Lines with circle stroke", renderer, TIME, re); // if everything worked we are going to have a red dot in the middle of the map assertEquals(Color.RED, getPixelColor(image, image.getWidth() / 2, image.getHeight() / 2)); assertEquals(Color.WHITE, getPixelColor(image, image.getWidth() / 4, image.getHeight() / 2)); assertEquals(Color.WHITE, getPixelColor(image, image.getWidth() / 2, image.getHeight() / 4)); assertEquals(Color.WHITE, getPixelColor(image, image.getWidth() / 4, image.getHeight() / 4)); }
@Test public void testDeadlockOnException() throws Exception { ReferencedEnvelope reWgs = new ReferencedEnvelope(new Envelope(-180, 180, -90, 90), DefaultGeographicCRS.WGS84); // create the grid coverage that throws a OOM BufferedImage testImage = new BufferedImage(200, 200, BufferedImage.TYPE_4BYTE_ABGR); GridCoverage2D testCoverage = new GridCoverageFactory().create("test", testImage, reWgs); GridCoverage2D oomCoverage = new GridCoverage2D("test", testCoverage) { @Override public RenderedImage getRenderedImage() { throw new OutOfMemoryError("Boom!"); } }; // also have a collections of features to create the deadlock once the painter // thread is dead SimpleFeatureCollection lines = createLineCollection(); Style rasterStyle = createRasterStyle(); Style lineStyle = createLineStyle(); MapContent mapContent = new MapContent(); mapContent.addLayer(new GridCoverageLayer(oomCoverage, rasterStyle)); mapContent.addLayer(new FeatureLayer(lines, lineStyle)); final StreamingRenderer sr = new StreamingRenderer() { // makes it easy to reproduce the deadlock, just two features are sufficient protected BlockingQueue<RenderingRequest> getRequestsQueue() { return new RenderingBlockingQueue(1); } }; sr.setMapContent(mapContent); final List<Exception> exceptions = new ArrayList<Exception>(); sr.addRenderListener( new RenderListener() { public void featureRenderer(SimpleFeature feature) { features++; } public void errorOccurred(Exception e) { errors++; exceptions.add(e); } }); errors = 0; features = 0; BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_4BYTE_ABGR); sr.paint((Graphics2D) image.getGraphics(), new Rectangle(200, 200), reWgs); // all the lines should have been painted, the coverage reports as painted too // since the reporting happens in the main thread that does not error assertEquals(4, features); assertEquals(1, errors); assertTrue(exceptions.get(0).getCause() instanceof OutOfMemoryError); }
private List<ZGroupLayerPainter> buildLayerPainters( Graphics2D graphics, StreamingRenderer renderer, String layerId, ProgressListener cancellationListener) throws IOException, FactoryException, NoninvertibleTransformException, SchemaException, TransformException { List<ZGroupLayerPainter> painters = new ArrayList<>(); boolean closePainters = true; try { for (Layer layer : layers) { // get the LiteFeatureTypeStyle for this layer final FeatureSource featureSource = layer.getFeatureSource(); if (featureSource == null) { throw new IllegalArgumentException("The layer does not contain a feature source"); } final FeatureType schema = featureSource.getSchema(); final ArrayList<LiteFeatureTypeStyle> lfts = renderer.createLiteFeatureTypeStyles(layer, graphics, false); if (lfts.isEmpty()) { continue; } else { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Processing " + lfts.size() + " stylers for " + schema.getName()); } } // get the feature iterator we need FeatureCollection features = renderer.getFeatures(layer, schema, lfts); // While we could use a non mark feature iterator for single fts layers, // that would cause multiple connections to be open at the same time, // which in turn could cause deadlocks against connection pools, so we // are going to build a MarkFeatureIterator regardless // TODO: we could optimize down to simple streaming painting if we end up // with a single painter with a single fts (due to scale dependencies) // but we'd have to delay opening the MarkFeatureIterator to recognize the // situation int maxFeatures = SortedFeatureReader.getMaxFeaturesInMemory(layer.getQuery()); MarkFeatureIterator fi = MarkFeatureIterator.create(features, maxFeatures, cancellationListener); if (fi.hasNext()) { ZGroupLayerPainter painter = new ZGroupLayerPainter(fi, lfts, renderer, layerId); painters.add(painter); } else { fi.close(); } } // got to the end cleanly, no need to close the painters accumulated so far closePainters = false; } finally { if (closePainters) { for (ZGroupLayerPainter painter : painters) { try { painter.close(); } catch (Exception e) { LOGGER.log(Level.FINE, "Failed to close cleanly layer painter " + painter, e); } } } } validateSortBy(painters); return painters; }
@Test public void testInfiniteLoopAvoidance() throws Exception { final Exception sentinel = new RuntimeException("This is the one that should be thrown in hasNext()"); // setup the mock necessary to have the renderer hit into the exception in hasNext() SimpleFeatureIterator it2 = createNiceMock(SimpleFeatureIterator.class); expect(it2.hasNext()).andThrow(sentinel).anyTimes(); replay(it2); SimpleFeatureCollection fc = createNiceMock(SimpleFeatureCollection.class); expect(fc.features()).andReturn(it2); expect(fc.size()).andReturn(200); expect(fc.getSchema()).andReturn(testLineFeatureType).anyTimes(); replay(fc); SimpleFeatureSource fs = createNiceMock(SimpleFeatureSource.class); expect(fs.getFeatures((Query) anyObject())).andReturn(fc); expect(fs.getSchema()).andReturn(testLineFeatureType).anyTimes(); expect(fs.getSupportedHints()).andReturn(new HashSet()).anyTimes(); replay(fs); // build map context MapContext mapContext = new DefaultMapContext(DefaultGeographicCRS.WGS84); mapContext.addLayer(fs, createLineStyle()); // setup the renderer and listen for errors final StreamingRenderer sr = new StreamingRenderer(); sr.setContext(mapContext); sr.addRenderListener( new RenderListener() { public void featureRenderer(SimpleFeature feature) { features++; } public void errorOccurred(Exception e) { errors++; if (errors > 2) { // we dont' want to block the loop in case of regression on this bug sr.stopRendering(); } // but we want to make sure we're getting Throwable t = e; while (t != sentinel && t.getCause() != null) t = t.getCause(); assertSame(sentinel, t); } }); errors = 0; features = 0; BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_4BYTE_ABGR); ReferencedEnvelope reWgs = new ReferencedEnvelope(new Envelope(-180, -170, 20, 40), DefaultGeographicCRS.WGS84); sr.paint((Graphics2D) image.getGraphics(), new Rectangle(200, 200), reWgs); // we should get two errors since there are two features that cannot be // projected but the renderer itself should not throw exceptions assertEquals(0, features); assertEquals(1, errors); }
@Test public void testScreenMapMemory() { // build a feature source with two zig-zag line occupying the same position LiteCoordinateSequence cs = new LiteCoordinateSequence(new double[] {0, 0, 1, 1, 2, 0, 3, 1, 4, 0}); SimpleFeature zigzag1 = SimpleFeatureBuilder.build( testLineFeatureType, new Object[] {gf.createLineString(cs)}, "zz1"); SimpleFeature zigzag2 = SimpleFeatureBuilder.build( testLineFeatureType, new Object[] {gf.createLineString(cs)}, "zz2"); DefaultFeatureCollection fc = new DefaultFeatureCollection(); fc.add(zigzag1); fc.add(zigzag2); SimpleFeatureSource zzSource = new CollectionFeatureSource(fc); // prepare the map MapContent mc = new MapContent(); StyleBuilder sb = new StyleBuilder(); mc.addLayer(new FeatureLayer(zzSource, sb.createStyle(sb.createLineSymbolizer()))); StreamingRenderer sr = new StreamingRenderer(); sr.setMapContent(mc); // collect rendered features final List<SimpleFeature> features = new ArrayList<SimpleFeature>(); RenderListener renderedFeaturesCollector = new RenderListener() { @Override public void featureRenderer(SimpleFeature feature) { features.add(feature); } @Override public void errorOccurred(Exception e) { // nothing to do } }; sr.addRenderListener(renderedFeaturesCollector); BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR); Graphics2D graphics = bi.createGraphics(); // have the lines be smaller than a 1/3 of a pixel sr.paint( graphics, new Rectangle(0, 0, 1, 1), new ReferencedEnvelope(0, 8, 0, 8, DefaultGeographicCRS.WGS84)); // check we only rendered one feature assertEquals(1, features.size()); assertEquals("zz1", features.get(0).getID()); // now have the lines be big enough to be painted instead features.clear(); sr.paint( graphics, new Rectangle(0, 0, 1, 1), new ReferencedEnvelope(0, 1, 0, 1, DefaultGeographicCRS.WGS84)); assertEquals(2, features.size()); assertEquals("zz1", features.get(0).getID()); assertEquals("zz2", features.get(1).getID()); graphics.dispose(); }