Resizing with FXGraphics2D and StreamingRenderer

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Resizing with FXGraphics2D and StreamingRenderer

Judicaël Bedouet
Hello,

We are developing a JavaFX application with a map designed with GeoTools. It works well but we have some issues while resizing. Below is a small example showing our issue.

import java.awt.Color;
import java.awt.Rectangle;

import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.JTSFactoryFinder;
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.DefaultGeographicCRS;
import org.geotools.renderer.lite.StreamingRenderer;
import org.geotools.styling.SLD;
import org.geotools.styling.Style;
import org.jfree.fx.FXGraphics2D;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class ResizingTest extends Application {

    @Override
    public void start(Stage stage) {

        Canvas canvas = new Canvas(640, 480);
        BorderPane root = new BorderPane(canvas);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();

        // Create bindings for resizing.
        canvas.widthProperty().bind(root.widthProperty());
        canvas.heightProperty().bind(root.heightProperty());

        SimpleFeatureTypeBuilder lineFeatureTypeBuilder = new SimpleFeatureTypeBuilder();
        lineFeatureTypeBuilder.setName("LineFeatureType");
        lineFeatureTypeBuilder.setCRS(DefaultGeographicCRS.WGS84);
        lineFeatureTypeBuilder.add("the_geom", LineString.class, DefaultGeographicCRS.WGS84);
        SimpleFeatureType lineFeatureType = lineFeatureTypeBuilder.buildFeatureType();
        SimpleFeatureBuilder lineFeatureBuilder = new SimpleFeatureBuilder(lineFeatureType);

        DefaultFeatureCollection lines = new DefaultFeatureCollection();

        Coordinate[][] cs = {
                { new Coordinate(-1, 42), new Coordinate(4, 46) },
                { new Coordinate(-1, 46), new Coordinate(4, 42) }
        };

        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
        for(Coordinate [] c : cs) {
            LineString line = geometryFactory.createLineString(c);
            lineFeatureBuilder.add(line);
            SimpleFeature feature = lineFeatureBuilder.buildFeature(null);
            lines.add(feature);
        }

        MapContent map = new MapContent();
        Style style = SLD.createLineStyle(Color.RED, 1);
        Layer layer = new FeatureLayer(lines, style);
        map.addLayer(layer);
        //map.getViewport().setBounds(new ReferencedEnvelope(-1, 4, 42, 46, DefaultGeographicCRS.WGS84));

        AnimationTimer loop = new AnimationTimer() {
            @Override
            public void handle(long now) {
                GraphicsContext g = canvas.getGraphicsContext2D();
                FXGraphics2D graphics = new FXGraphics2D(g);
                graphics.setBackground(java.awt.Color.BLUE);
                Rectangle rectangle = new Rectangle( (int) canvas.getWidth(), (int) canvas.getHeight());
                graphics.clearRect(0, 0, (int) rectangle.getWidth(), (int) rectangle.getHeight());
                graphics.drawRect(100, 100, 100, 100);
                map.getViewport().setScreenArea(rectangle); // Necessary ?
                StreamingRenderer renderer = new StreamingRenderer();
                renderer.setMapContent(map);
                renderer.paint(graphics, rectangle, map.getViewport().getBounds());
                System.out.println("ScreenArea: " + map.getViewport().getScreenArea() + " - Viewport: " + map.getViewport().getBounds());
            }
        };
        loop.start();
       
    }

    public static void main(String[] args) {
        launch(args);
    }

}


You should see a black square (in screen coordinates) drawn with FXGraphics2D and a red cross (in WGS84 coordinates) drawn with the GeoTools streaming renderer.

If you enlarge the window, the square keeps the same size and the cross is bigger. Perfect ! This is what we want. But the scene is not completely rendered.

Inline image 1

We were wondering if we were not using correctly JavaFX or FXGraphics2D but if you comment the line 87 (renderer.paint(graphics, rectangle, map.getViewport().getBounds());), it works (but no red cross).

See the image fxresizing3.png

If you uncomment the line 87 and comment the line 72 (map.addLayer(layer)), it still works (with many exceptions and still without the red cross).

So, our issue seems to be related to the FeatureLayer class. As soon as we want to render a feature layer, a part of the screen is not rendered. Any idea ? What are we doing wrong ? Is it a bug in GeoTools ? In FXGraphics2D ? It works well with the JMapFrame to render the same layer.

Our configuration is JRE 1.8.0_144, GeoTools 17.2 and FXGraphics2D 1.5.

Best regards,

J. Bedouet

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
GeoTools-GT2-Users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/geotools-gt2-users