2012-01-31 106 views
0

Overlapping labels檢測重疊ticklabels

正如你可以看到,當擋位軸跨越大面積,以及ticklabels得太近了,他們開始重疊。我想實現某種邏輯來檢測它們是否重疊,如果是,則只顯示一個首選(或最多可以匹配)。但是,我有點不確定如何做到這一點。

的邏輯是這樣的:

  1. 優先每個標籤的重要性後
  2. 獲取每個刻度標記的使用Java2D保持座標(X,Y,寬,高)
  3. 如果一個標籤的區域與另一個重疊,只顯示最重要的一個

但是有哪些方法可以做到這一點?從我買的API文檔中,我發現這種方法

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

但是這個區域和邊緣我需要提供的功能?如果一個ticklabel,我將如何獲得寬度和高度?這是否是正確的方式呢?還是有更好的方法可以帶來成功?

+0

線性範圍軸。沒有工具提示。沒有縮放。只需在軸上自定義標籤 - 每行一個(深綠色區域中的上,中,下)。 – oligofren 2012-02-02 21:34:15

+0

好點!不幸的是,這是客戶的要求... – oligofren 2012-02-03 09:45:33

+0

交叉發佈[這裏](http://www.jfree.org/forum/viewtopic.php?f=3&t=109993)。 – trashgod 2012-05-06 21:35:24

回答

0

我在JFree論壇上發佈了這個問題(發現了垃圾內容),並獲得了一些不錯的提示there。我在那裏發佈的解決我問題的最終代碼如下:

@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); 
    } 
}