@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());
  }
Example #10
0
  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);
  }
Example #17
0
  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();
  }