package jeql.workbench.ui.geomview; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.Shape; import java.awt.Stroke; import jeql.workbench.ui.geomview.style.BasicStyle; import jeql.workbench.ui.geomview.style.Style; import com.vividsolutions.jts.awt.PointShapeFactory; import com.vividsolutions.jts.awt.ShapeWriter; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; public class GeometryPainter { private static Stroke GEOMETRY_STROKE = new BasicStroke(); private static Stroke POINT_STROKE = new BasicStroke(AppConstants.POINT_SIZE); static Viewport viewportCache; static ShapeWriter converterCache; /** * Choose a fairly conservative decimation distance to avoid visual artifacts */ private static final double DECIMATION_DISTANCE = 1.3; // TODO: is this a performance problem? // probably not - only called once for each geom painted public static ShapeWriter getConverter(Viewport viewport) { ShapeWriter sw = new ShapeWriter(viewport, new PointShapeFactory.Point()); //sw.setRemoveDuplicatePoints(true); //sw.setDecimation(viewport.toModel(DECIMATION_DISTANCE)); return sw; } /** * Paints a geometry onto a graphics context, * using a given Viewport. * * @param geometry shape to paint * @param viewport * @param g the graphics context * @param lineColor line color (null if none) * @param fillColor fill color (null if none) */ public static void paint(Geometry geometry, Viewport viewport, Graphics2D g, BasicStyle style) { ShapeWriter converter = getConverter(viewport); paint(geometry, converter, g, style); } private static void paint(Geometry geometry, ShapeWriter converter, Graphics2D g, BasicStyle style) { if (geometry == null) return; if (geometry instanceof GeometryCollection) { GeometryCollection gc = (GeometryCollection) geometry; /** * Render each element separately. * Otherwise it is not possible to render both filled and non-filled * (1D) elements correctly */ for (int i = 0; i < gc.getNumGeometries(); i++) { paint(gc.getGeometryN(i), converter, g, style); } return; } Shape shape = converter.toShape(geometry); Color lineColor = style.getLineColor(); Paint fillColor = style.getFillColor(); // handle points in a special way for appearance and speed if (geometry instanceof Point) { g.setStroke(POINT_STROKE); g.setPaint(lineColor); g.draw(shape); g.fill(shape); return; } Stroke stroke = style.getStroke(); if (stroke == null) g.setStroke(GEOMETRY_STROKE); else g.setStroke(stroke); // Test for a polygonal shape and fill it if required if (geometry instanceof Polygon && fillColor != null) { g.setPaint(fillColor); g.fill(shape); } if (lineColor != null) { g.setColor(lineColor); try { g.draw(shape); } catch (Throwable ex) { System.out.println(ex); // eat it! } } } }