TickUnits use wrong hours

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
Qohelet
Posts: 5
Joined: Thu Oct 08, 2009 9:57 am
antibot: No, of course not.

TickUnits use wrong hours

Post by Qohelet » Thu Oct 08, 2009 10:22 am

Hello!

I'm using jFreeChart 1.0.13 and I want to set a TickUnit every six hours. At 6, 12, 18 and 24:00. For this I used the following Code:

Code: Select all

((DateAxis) plot.getDomainAxis()).setTickUnit(new DateTickUnit(DateTickUnitType.HOUR,6, new SimpleDateFormat("EE dd.MM HH")));
((DateAxis) plot.getDomainAxis()).setTickMarkPosition(DateTickMarkPosition.START);
And it was possible to create this Chart with my Test-Data - the TickUnits are all on the right place:
Image

So I copied the Java-Classes in a JSP-Webproject to work with the real data. Now the Units are placed on 5, 11, 17 and 23:00:
Image

How can I fix this Problem? Thanks for your help!

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: TickUnits use wrong hours

Post by david.gilbert » Thu Oct 08, 2009 10:02 pm

I'm a little puzzled, because the DateAxis class doesn't support rotated labels, but you have them in the sample charts.

My guess would be that a time zone difference is affecting your chart, but I don't know if that is in the dataset, the axis, or the DateFormatter you are using.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

Qohelet
Posts: 5
Joined: Thu Oct 08, 2009 9:57 am
antibot: No, of course not.

Re: TickUnits use wrong hours

Post by Qohelet » Fri Oct 09, 2009 7:07 am

It's not very difficult to do this - DateAxis has to be changed a little bit:

1. I need two new variables

Code: Select all

private double winkel;                      //The angle I need
private boolean mywinkel = false;     //Do I need the angle?
2. Then I need getter/setter:

Code: Select all

    public double getWinkel() {
        return winkel;
    }

    public void setWinkel(double winkel) {
        this.mywinkel = true;
        this.winkel = Math.toRadians(winkel);
    }

    public boolean isMywinkel() {
        return mywinkel;
    }
3. And then I change the refreshTicksHorizontal-Method at the if-Statements:

Code: Select all

if (isVerticalTickLabels()) {
                    anchor = TextAnchor.CENTER_RIGHT;
                    rotationAnchor = TextAnchor.CENTER_RIGHT;
                    if (edge == RectangleEdge.TOP) {
                        angle = Math.PI / 2.0;
                    } else {
                        angle = -Math.PI / 2.0;
                    }
                } 
                if (isMywinkel()) {
                    System.out.println("meiwinkl");
                    anchor = TextAnchor.CENTER_RIGHT;
                    rotationAnchor = TextAnchor.CENTER_RIGHT;
                    if (edge == RectangleEdge.TOP) {
                        angle = getWinkel();
                    } else {
                        angle = -getWinkel();
                    }
                }
                else {
                    if (edge == RectangleEdge.TOP) {
                        anchor = TextAnchor.BOTTOM_CENTER;
                        rotationAnchor = TextAnchor.BOTTOM_CENTER;
                    } else {
                        anchor = TextAnchor.TOP_CENTER;
                        rotationAnchor = TextAnchor.TOP_CENTER;
                    }
                }
4. And the refreshTicksVertical-Method also at the Statements:

Code: Select all

if (isVerticalTickLabels()) {
                    anchor = TextAnchor.BOTTOM_CENTER;
                    rotationAnchor = TextAnchor.BOTTOM_CENTER;
                    if (edge == RectangleEdge.LEFT) {
                        angle = -Math.PI / 2.0;
                    } else {
                        angle = Math.PI / 2.0;
                    }
                }                
                if (isMywinkel()) {
                    System.out.println("meiwinkl");
                    anchor = TextAnchor.BOTTOM_CENTER;
                    rotationAnchor = TextAnchor.BOTTOM_CENTER;
                    if (edge == RectangleEdge.LEFT) {
                        angle = -this.winkel;
                    } else {
                        angle = this.winkel;
                    }
                }
                else {
                    if (edge == RectangleEdge.LEFT) {
                        anchor = TextAnchor.CENTER_RIGHT;
                        rotationAnchor = TextAnchor.CENTER_RIGHT;
                    } else {
                        anchor = TextAnchor.CENTER_LEFT;
                        rotationAnchor = TextAnchor.CENTER_LEFT;
                    }
                }
5. And in my program it looks like this:

Code: Select all

((DateAxis) plot.getDomainAxis()).setVerticalTickLabels(true);
((DateAxis) plot.getDomainAxis()).setWinkel(47.9);
chart.getLegend().setPosition(RectangleEdge.RIGHT);

Qohelet
Posts: 5
Joined: Thu Oct 08, 2009 9:57 am
antibot: No, of course not.

Re: TickUnits use wrong hours

Post by Qohelet » Fri Oct 09, 2009 7:18 am

But back to my question... No - I don't think that the TimeZone is the problem because the old project works correctly and my location hasn't changed - or do you mean something particular?

Here are the important parts of my Program:

Code: Select all

this.chart = ChartFactory.createCandlestickChart(
                    this.mainTitle,
                    this.getDaname(),
                    this.getRaname(),
                    this.getDhld(),    /* A defaultHighLowDataset*/
                    true);

        XYPlot plot = chart.getXYPlot();

        plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
        DateAxis dax = (DateAxis) plot.getDomainAxis();

        dax.setTickMarkPosition(DateTickMarkPosition.MIDDLE);

        ValueAxis axis = new NumberAxis(this.getRaname());
        plot.setRangeAxisLocation(i, AxisLocation.BOTTOM_OR_LEFT);

        ((DateAxis) plot.getDomainAxis()).setTickUnit(getTickunit());
        ((DateAxis) plot.getDomainAxis()).setTickMarkPosition(DateTickMarkPosition.START);

        ((DateAxis) plot.getDomainAxis()).setVerticalTickLabels(true);
        ((DateAxis) plot.getDomainAxis()).setWinkel(getAngle());
        chart.getLegend().setPosition(RectangleEdge.RIGHT);

                DateAxis das = (DateAxis) plot.getDomainAxis();
                Date lower = das.getMinimumDate();
                Date higher = das.getMaximumDate();

                long millis = lower.getTime();


                do {
                    final Marker originalEnd = new ValueMarker(millis);

                    originalEnd.setPaint(Color.BLACK);
                    originalEnd.setStroke(new BasicStroke((float) 1.5));
                    plot.addDomainMarker(originalEnd);

                    RegularTimePeriod myrtp = RegularTimePeriod.createInstance(this.rtp.getClass(), new Date(millis), TimeZone.getDefault());
                    myrtp = myrtp.next();
                    millis = myrtp.getFirstMillisecond();

                } while (millis <= higher.getTime());
That's it... Do you have any ideas...?

edit: Another reason why I don't think that the problem is the timezone: All values are displayed correct - just moved

Qohelet
Posts: 5
Joined: Thu Oct 08, 2009 9:57 am
antibot: No, of course not.

Re: TickUnits use wrong hours

Post by Qohelet » Fri Oct 16, 2009 8:45 am

No idea...?

Could it be a bug?

keshava
Posts: 2
Joined: Fri Aug 28, 2009 8:10 am
antibot: No, of course not.

Re: TickUnits use wrong hours

Post by keshava » Thu Mar 25, 2010 7:14 am

Hi,

Can We use the above mentioned code to display labels at an angle.. The official Jfreechart library doesn't support it, and I'm wondering there must be a reason not to do it . They would have incorporated it if it would have been a simple fix..

@ Gilbert ,
Any inputs whether we can use that ??

jleech
Posts: 62
Joined: Fri Oct 26, 2007 9:18 pm

Re: TickUnits use wrong hours

Post by jleech » Mon Mar 29, 2010 7:36 pm

David, Keshava
Here is my version of rotated labels, which also sets the height properly. (replace Math.PI / -4.0 with your favorite angle in radians) Biggest issue I see with incorporating it into JFreechart codebase would be that if the labels are long enough, and the Y-axis not wide enough, the left edge of the label text can be clipped off the chart. The code would have to calculate the room necessary for the label, and if there isn't room, would have to adjust the left padding as necessary.
-Jonathan

Code: Select all

final DateAxis axis = new DateAxis(xAxisLabel) {
               @SuppressWarnings("unchecked")
               @Override
               protected List refreshTicksHorizontal(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge) {
                  List ticks = super.refreshTicksHorizontal(g2, dataArea, edge);
                  List ret = new ArrayList();
                  for (Tick tick : (List<Tick>)ticks) {
                     if (tick instanceof DateTick) {
                        DateTick dateTick = (DateTick)tick;
                        ret.add(new DateTick(dateTick.getDate(), dateTick.getText(), dateTick.getTextAnchor(), dateTick.getRotationAnchor(), Math.PI / -4.0));
                     } else {
                        ret.add(tick);
                     }
                  }
                  return ret;
               }
               protected double findMaximumTickLabelHeight(java.util.List ticks, java.awt.Graphics2D g2, java.awt.geom.Rectangle2D drawArea, boolean vertical) {
                  return super.findMaximumTickLabelHeight(ticks, g2, drawArea, vertical) * Math.sin(Math.PI / 4.0);
               }
};
axis.setVerticalTickLabels(true);
plot.setDomainAxis(axis);

Locked