0

When I add osm service in a mapContent

mapContent.addLayer(new AsyncTileLayer(new OSMService("Mapnik", "http://tile.openstreetmap.org/")));

Then when I use the paint method of StreamingRenderer class, there is an infinite run. More precisely the infinite run occurs in the line 563 of the StreamingRenderer class file with :

painterFuture.get();

I call paint method to paint what I add to the mapContent, i.e. here the featureLayer and the osm map.

MapContent mapContent = new MapContent();
mapContent.addLayer(new AsyncTileLayer(new OSMService("Mapnik", "http://tile.openstreetmap.org/")));

CoordinateReferenceSystem crs = CRS.decode("EPSG:4326", true);
ReferencedEnvelope envelope = new ReferencedEnvelope(566516.1128181651, 571832.3519307065, 5275726.889218023, 5281104.067690026, crs);
mapContent.getViewport().setBounds(envelope);

GTRenderer renderer = new StreamingRenderer();
renderer.setMapContent(mapContent);

Rectangle imageBounds;
ReferencedEnvelope mapBounds;
try {
    mapBounds = mapContent.getMaxBounds();
    double heightToWidth = mapBounds.getSpan(1) / mapBounds.getSpan(0);
    imageBounds = new Rectangle(5, 5, 1000, (int) Math.round(1000 * heightToWidth));
} catch (Exception e) {
    throw new RuntimeException(e);
}

BufferedImage mapBufferedImage = new BufferedImage(imageBounds.width, imageBounds.height, BufferedImage.TYPE_INT_ARGB);
Graphics2D gr = mapBufferedImage.createGraphics();
renderer.paint(gr, imageBounds, mapBounds);

Here is the content of the painterFuture object : state = 0, callable = java.util.concurrent.Executors$RunnableAdapter@3533df16[Wrapped task = org.geotools.renderer.lite.StreamingRenderer$PainterThread@15d0849], outcome = null, runner = "Thread[pool-1-thread-1,5,main]", waiters = null

When there is just the featureLayer and not the osm service, the painterFuture object is marked as Completed normally and contains : state = 2, callable = null, outcome = null, runner = null, waiters = null.

With this following code I get an image but that doesn't seems to be the good projection.

ReferencedEnvelope re = layer.getBounds();
mapContent.addLayer(new AsyncTileLayer(new OSMService("Mapnik", "http://tile.openstreetmap.org/")));

CoordinateReferenceSystem source = CRS.decode("EPSG:25832");
CoordinateReferenceSystem target = CRS.decode("EPSG:4326");

MathTransform transform = CRS.findMathTransform(source, target, true);
Envelope targetGeometry = JTS.transform(re, transform);

ReferencedEnvelope envelope = new ReferencedEnvelope(targetGeometry, target);

mapContent.getViewport().setBounds(envelope);
6
  • Did you try turning logging to fine or stepping through with a debugger?
    – Ian Turton
    Commented May 11, 2022 at 14:14
  • @IanTurton, Yes I stepped through with a debugger, that is how I knew that the problem was in the paint method of the StreamingRenderer class. Here is the content of the painterFuture object : state = 0, callable = java.util.concurrent.Executors$RunnableAdapter@3533df16[Wrapped task = org.geotools.renderer.lite.StreamingRenderer$PainterThread@15d0849], outcome = null, runner = "Thread[pool-1-thread-1,5,main]", waiters = null
    – adrbessy
    Commented May 12, 2022 at 9:03
  • your example code doesn't work - but gives me an error WARNING: Width (0) and height (0) cannot be <= 0 java.lang.IllegalArgumentException: Width (0) and height (0) cannot be <= 0 at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1016) at java.awt.image.BufferedImage.<init>(BufferedImage.java:333) at org.geotools.tile.util.TileLayer.createImage(TileLayer.java:168) at org.geotools.tile.util.TileLayer.draw(TileLayer.java:85) at org.geotools.renderer.lite.CompositingGroup$WrappingDirectLayer.draw(CompositingGroup.java:227) at
    – Ian Turton
    Commented May 14, 2022 at 15:28
  • @IanTurton, Sorry, I didn't change the variable name "map" to "mapContent" in this example to get the maxBounds.
    – adrbessy
    Commented May 16, 2022 at 7:40
  • Please post a small working example that demonstrates your problem
    – Ian Turton
    Commented May 16, 2022 at 8:01

1 Answer 1

0

The problem seems to be that you are asking for an area the size of millions of Earths across, so it takes a long time to calculate all the possible (empty) tiles that need to be requested from the OSM server.

CoordinateReferenceSystem crs = CRS.decode("EPSG:4326", true);
ReferencedEnvelope envelope = new ReferencedEnvelope(566516.1128181651, 571832.3519307065, 5275726.889218023, 5281104.067690026, crs);
mapContent.getViewport().setBounds(envelope);

is the problem, those coordinates are clearly not in EPSG:4326 (which is in degrees and runs from -180,180 and -90,90. I suspect you mean EPSG:3857 (Web Mercator).

Fixing that lead to another problem which was that you were exceeding the MaxTileLimit of 128 and also requesting tiles of size 0x0 in the tile layer.

This is because your screen area was 0x0 - so adding the line:

mapContent.getViewport().setScreenArea(imageBounds);

made it run with out error.

Update

Here is the code I used to test.

package spike;

import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;

import org.geotools.data.FileDataStore;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.FeatureLayer;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.referencing.CRS;
import org.geotools.renderer.GTRenderer;
import org.geotools.renderer.lite.StreamingRenderer;
import org.geotools.styling.SLD;
import org.geotools.tile.impl.osm.OSMService;
import org.geotools.tile.util.AsyncTileLayer;
import org.geotools.util.URLs;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.TransformException;

public class OSMLayer {

  public static void main(String[] args)
      throws IOException, NoSuchAuthorityCodeException, TransformException, FactoryException {

    FileDataStore ds = new ShapefileDataStore(URLs.fileToUrl(new File("/home/ian/Data/states/states.shp")));


    Layer featureLayer = new FeatureLayer(ds.getFeatureSource().getFeatures(), SLD.createSimpleStyle(ds.getSchema()));
    MapContent mapContent = new MapContent();
    mapContent.addLayer(new AsyncTileLayer(new OSMService("Mapnik", "http://tile.openstreetmap.org/")));
    mapContent.addLayer(featureLayer);
    CoordinateReferenceSystem crs = CRS.decode("EPSG:3857", true);
    ReferencedEnvelope envelope = new ReferencedEnvelope(566516.1128181651, 571832.3519307065, 5275726.889218023,
        5281104.067690026, crs);
    mapContent.getViewport().setBounds(featureLayer.getBounds().transform(crs, false));

    GTRenderer renderer = new StreamingRenderer();
    renderer.setMapContent(mapContent);

    Rectangle imageBounds;
    ReferencedEnvelope mapBounds;
    try {
      mapBounds = mapContent.getViewport().getBounds();
      double heightToWidth = mapBounds.getSpan(1) / mapBounds.getSpan(0);
      imageBounds = new Rectangle(5, 5, 1000, (int) Math.round(1000 * heightToWidth));
    } catch (Exception e) {
      throw new RuntimeException(e);
    }

    BufferedImage mapBufferedImage = new BufferedImage(imageBounds.width, imageBounds.height,
        BufferedImage.TYPE_INT_ARGB);
    mapContent.getViewport().setScreenArea(imageBounds);
    Graphics2D gr = mapBufferedImage.createGraphics();
    renderer.paint(gr, imageBounds, mapBounds);
    try (FileOutputStream fileOutputStream = new FileOutputStream(new File("out.png"));
        ImageOutputStream outputImageFile = ImageIO.createImageOutputStream(fileOutputStream)) {

      ImageIO.write(mapBufferedImage, "png", outputImageFile);
    } catch (IOException ex) {
      ex.printStackTrace();
    }
  }

}

With my US States layer (mapContent.getViewport().setBounds(featureLayer.getBounds().transform(crs, false)); ) it gives this output:

enter image description here

With your bounding box (mapContent.getViewport().setBounds(envelope);)it gives:

enter image description here

3
  • I tried with CoordinateReferenceSystem crs = CRS.decode("EPSG:3857", true); and mapContent.getViewport().setScreenArea(imageBounds); but this gives the same effect...
    – adrbessy
    Commented May 20, 2022 at 7:19
  • I tried with : CoordinateReferenceSystem crs = CRS.decode("EPSG:3857", true); mapContent.getViewport().setBounds(layer.getBounds().transform(crs, false)); But the output says the longitude and latitude are out of their allowed limits.
    – adrbessy
    Commented May 20, 2022 at 12:38
  • Then your layer bounds are wrong but that is a new question
    – Ian Turton
    Commented May 20, 2022 at 13:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.