Обнаружение перекрывающихся меток - PullRequest
0 голосов
/ 31 января 2012

Overlapping labels

Как вы можете видеть, когда ось диапазона охватывает большую область, а метки слишком близко друг к другу, они начинают перекрываться.Я хотел бы реализовать какую-то логику, чтобы определить, перекрываются ли они, и если это так, просто показать предпочитаемую (или столько, сколько будет соответствовать).Однако я немного не уверен, как этого добиться.

Логика будет выглядеть примерно так:

  1. Приоритет каждой метки после важности
  2. Получить координаты Java2d каждой метки тика (x, y, ширина), высота)
  3. Если область метки перекрывается с другой, просто покажите самую важную

Но какие методы доступны для этого?Из документов API, которые я купил, я нашел этот метод

public double valueToJava2D(double value, Rectangle2D area, RectangleEdge edge);

Но для чего нужна эта область и ребро, чтобы обеспечить функцию?И как бы я взял ширину и высоту, если метка?И это правильный путь, или есть лучший путь, который приведет к успеху?

1 Ответ

0 голосов
/ 10 мая 2012

Я разместил вопрос на форумах JFree (как нашёл trashgod) и получил несколько хороших подсказок там . Последний код, который я разместил там, который решил мою проблему, был следующим:

@SuppressWarnings({"RawUseOfParameterizedType", "serial"})
private static class CustomTickMarkNumberAxis extends NumberAxis {
    private double[] customTicksSortedOnImportance;

    /**
     * A list ticks sorted after importance. In case of overlapping,
     * a higher ranked tick will trump a lower ranked tick, thus <i>not showing</i>
     * the lower ranked (overlapping) tick.
     * Other lower ranked ticks might still be shown, if they are not overlapping
     */
    public CustomTickMarkNumberAxis(double[] customTicksSortedOnImportance) {
        this.customTicksSortedOnImportance = customTicksSortedOnImportance;
    }

    protected List<NumberTick> refreshTicksVertical(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge) {
        List<NumberTick> result = new java.util.ArrayList<NumberTick>();

        //(... snip ...)

        Area tickLabelArea = new Area(); /** Used for overlap detection */
        for (int i = 0; i < customTicksSortedOnImportance.length; i++) {
            // The next lines of code are different from NumberAxis
            double currentTickValue = customTicksSortedOnImportance[i];
            currentTickValue = NumberUtil.round(currentTickValue, precision);

            //(... snip ...)

            /* Overlapping logic here */
            NumberTick numberTick = new NumberTick(currentTickValue, tickLabel, anchor, rotationAnchor, angle);
            Rectangle2D labelBounds = getTickBounds(numberTick, g2);
            double java2dValue = valueToJava2D(currentTickValue, g2.getClipBounds(), edge);
            labelBounds.setRect(labelBounds.getX(), java2dValue, labelBounds.getWidth(), labelBounds.getHeight());

            if (!tickLabelIsOverlapping(tickLabelArea, labelBounds)) {
                result.add(numberTick);
                tickLabelArea.add(new Area(labelBounds));
            }

            //(... snip ...)
        }
        return result;
    }

    private boolean tickLabelIsOverlapping(Area area, Rectangle2D rectangle) {
        return area.intersects(rectangle);
    }

    private Rectangle2D getTickBounds(NumberTick numberTick, Graphics2D g2) {
        FontMetrics fm = g2.getFontMetrics(getTickLabelFont());
        return TextUtilities.getTextBounds(numberTick.getText(), g2, fm);
    }
}
...