Обнаружение перекрывающихся меток

Перекрывающиеся метки

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

Логика будет примерно такой:

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

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

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

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


person oligofren    schedule 31.01.2012    source источник
comment
Ось линейного диапазона. Нет подсказки. Нет зума. Просто настроены галочки на оси - по одной на каждую строку (верхняя, средняя, ​​нижняя в темно-зеленой области).   -  person oligofren    schedule 03.02.2012
comment
Хорошая точка зрения! К сожалению, это было требование от клиента...   -  person oligofren    schedule 03.02.2012
comment
Опубликовано здесь.   -  person trashgod    schedule 07.05.2012
comment
Да, это мой пост с моим ответом. Отвечаю и здесь.   -  person oligofren    schedule 10.05.2012


Ответы (1)


Я разместил вопрос на форумах 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);
    }
}
person oligofren    schedule 10.05.2012