view gnv-artifacts/src/main/java/de/intevation/gnv/jfreechart/PolygonRenderer.java @ 522:c896282c2601

Issue 156 solved. Added width, height and points as parameter to svg and pdf output mode. Width and height have an effact on the width and height of the export, points is a boolean property which enables/disables the drawing of data points. gnv-artifacts/trunk@616 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Mon, 25 Jan 2010 09:18:31 +0000
parents bc5901bb4525
children 9a828e5a2390
line wrap: on
line source
package de.intevation.gnv.jfreechart;

import java.util.ArrayList;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.BasicStroke;
import java.awt.FontMetrics;
import java.awt.Font;

import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Rectangle2D.Double;

import org.jfree.data.Range;

import org.jfree.chart.axis.ValueAxis;

import org.jfree.ui.RectangleEdge;

import org.apache.log4j.Logger;

import org.jfree.text.TextUtilities;


/**
 * @author Ingo Weinzierl      (ingo.weinzierl@intevation.de)
 * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
 */
public class PolygonRenderer
{
	private static Logger log = Logger.getLogger(
		PolygonRenderer.class);

    public interface PaintLookup {

        Paint getPaint(int index);

    } // interface PaintLookup

    public static class DefaultLabelGenerator
    implements          PolygonSeriesLabelGenerator
    {
        public DefaultLabelGenerator() {
        }

        public String generateLabel(PolygonSeries series) {
            Object label = series.getAttribute("label");
            return label != null
                ? toString(label)
                : null;
        }

        protected String toString(Object label) {
            return label.toString();
        }
    } // class DefaultLabelGenerator

    public static final PolygonSeriesLabelGenerator 
        DEFAULT_LABEL_GENERATOR_INSTANCE = new DefaultLabelGenerator();

    protected PaintLookup                 lookup;
    protected PolygonSeriesLabelGenerator labelGenerator;

    public PolygonRenderer(PaintLookup lookup) {
        this(lookup, null);
    }

    public PolygonRenderer(
        PaintLookup                 lookup, 
        PolygonSeriesLabelGenerator labelGenerator
    ) {
        this.lookup         = lookup;
        this.labelGenerator = labelGenerator;
    }

    public void drawPolygons(
        Graphics2D     graphics,
        PolygonPlot    plot,
        Rectangle2D    area,
        PolygonDataset dataset
    ) {
        int seriesCount = dataset.getSeriesCount();
        for (int i = 0; i < seriesCount; i++) {
            PolygonSeries series   = dataset.getSeries(i);
            Integer       colorIdx = (Integer)series.getAttribute("fill");

            if (colorIdx != null) {
                Paint paint = lookup.getPaint(colorIdx.intValue());
                graphics.setPaint(paint != null ? paint : Color.black);
                graphics.fill(constructShape(plot, area, series, true));
            }
            else {
                Number lineWidth = (Number)series.getAttribute("line.width");
                BasicStroke stroke = new BasicStroke(
                    lineWidth != null ? lineWidth.floatValue() : 1f);
                graphics.setStroke(stroke);
                graphics.setPaint(Color.black);
                graphics.draw(constructShape(plot, area, series, false));
            }
        }
    }

    public void drawLabels(
        final Graphics2D  graphics,
        final PolygonPlot plot,
        final Rectangle2D area,
        PolygonDataset    dataset
    ) {
        if (labelGenerator == null) {
            return;
        }

        final ArrayList<Rectangle2D> bboxes = new ArrayList<Rectangle2D>();

        Font font = graphics.getFont();
        font = font.deriveFont(Font.PLAIN, Math.max(8, font.getSize()-3));
        graphics.setFont(font);
        FontMetrics metrics = graphics.getFontMetrics(font);

        for (int i = dataset.getSeriesCount()-1; i >= 0; --i) {
            PolygonSeries series = dataset.getSeries(i);

            String label = labelGenerator.generateLabel(series);
            if (label == null) {
                continue;
            }

            final Rectangle2D box = TextUtilities.getTextBounds(
                label, graphics, metrics);

            for (int j = series.getItemCount()-1; j >= 0; --j) {
                final CompactXYItems ring = series.getItem(j);
                LevelOrderIndices loi = new LevelOrderIndices(ring.size()-1);
                Rectangle2D r = (Rectangle2D)loi.visit(
                    new LevelOrderIndices.Visitor() 
                {
                    ValueAxis          da = plot.getDomainAxis();
                    ValueAxis          ra = plot.getRangeAxis();
                    RectangleEdge      de = plot.getDomainAxisEdge();
                    RectangleEdge      re = plot.getRangeAxisEdge();
                    Rectangle2D.Double r  = new Rectangle2D.Double(
                        0d, 0d, box.getWidth(), box.getHeight());

                    public Object visit(int index) {
                        r.x = da.valueToJava2D(ring.getX(index), area, de) 
                            - 0.5*box.getWidth();
                        r.y = ra.valueToJava2D(ring.getY(index), area, re)
                            + 0.5*box.getHeight();

                        for (Rectangle2D b: bboxes) {
                            if (b.intersects(r)) {
                                return null;
                            }
                        }
                        return r;
                    }
                });

                if (r != null) {
                    bboxes.add(r);
                    graphics.drawString(
                        label, (float)r.getX(), (float)r.getY());
                }
            } // for all items in series
        } // for all series
    }

    protected Shape constructShape(
        PolygonPlot   plot,
        Rectangle2D   area,
        PolygonSeries series, 
        boolean       close
    ) {
        ValueAxis     da = plot.getDomainAxis();
        ValueAxis     ra = plot.getRangeAxis();
        RectangleEdge de = plot.getDomainAxisEdge();
        RectangleEdge re = plot.getRangeAxisEdge();

        CompactXYItems [] rings = series.getRings();
        GeneralPath       path  = new GeneralPath();

        for (int i = 0; i < rings.length; ++i) {

            CompactXYItems ring = rings[i];

            double [] data = ring.getData();

            if (data.length >= 2) {
                path.moveTo(
                    (float)da.valueToJava2D(data[0], area, de),
                    (float)ra.valueToJava2D(data[1], area, re));
            }
            for (int j = 2; j < data.length;) {
                path.lineTo(
                    (float)da.valueToJava2D(data[j++], area, de),
                    (float)ra.valueToJava2D(data[j++], area, re));
            }
            if (close) {
                path.closePath();
            }
        }
        return path;
    }

    public Rectangle2D getBoundingBox(PolygonDataset dataset) {
        Rectangle2D bbox = null;

        for (int i = 0, N = dataset.getSeriesCount(); i < N; i++) {
            Range domain = dataset.getSeries(i).getDomainBounds();
            Range range  = dataset.getSeries(i).getRangeBounds();

            double x = domain.getLowerBound();
            double y = range.getLowerBound();
            double w = Math.abs(domain.getUpperBound() - x);
            double h = Math.abs(range.getUpperBound() - y);

            if (bbox == null) {
                bbox = new Rectangle2D.Double(x, y, w, h);
            }
            else {
                bbox.add(new Rectangle2D.Double(x, y, w, h));
            }
        }

        return bbox;
    }

    public Rectangle2D getBounds(PolygonSeries series) {

        Range domain = series.getDomainBounds();
        Range range  = series.getRangeBounds();

        return new Rectangle2D.Double(
            domain.getLowerBound(), range.getLowerBound(),
            domain.getUpperBound(), range.getUpperBound()
        );
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org