Polar Axis Location incorrect for West and South

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
sildon
Posts: 6
Joined: Sat Sep 26, 2020 10:31 am
antibot: No, of course not.

Polar Axis Location incorrect for West and South

Post by sildon » Sat Sep 26, 2020 10:41 am

When I change the axis location to either west or south, zero is no longer in the center but on the outside edge. Or stated another way, the upper bounds value is in the center and the lower bounds value is at the west or south angel tick mark. Is this a bug, or is there something else I need to do to keep the lower bound (always zero in my case) in the center of the polar plot?

John Matthews
Posts: 513
Joined: Wed Sep 12, 2007 3:18 pm

Re: Polar Axis Location incorrect for West and South

Post by John Matthews » Mon Sep 28, 2020 12:28 am

It sounds like you need to invert the ValueAxis used by the PolarPlot:

Code: Select all

ValueAxis radiusAxis = new NumberAxis();
radiusAxis.setInverted(true);

sildon
Posts: 6
Joined: Sat Sep 26, 2020 10:31 am
antibot: No, of course not.

Re: Polar Axis Location incorrect for West and South

Post by sildon » Mon Sep 28, 2020 8:56 am

Inverting the axis makes things worse. Although the axis labels are reversed, the data becomes distorted. I didn't look very closely at what happens, but from a quick look it appears some values became negative (or the angle was altered by 180 deg) so that data which should be only on the east side of the plot was on both the east and west side.

John Matthews
Posts: 513
Joined: Wed Sep 12, 2007 3:18 pm

Re: Polar Axis Location incorrect for West and South

Post by John Matthews » Mon Sep 28, 2020 11:59 pm

Using the example examined here, I had no trouble with code that sets the location of the primary axis, e.g.

Code: Select all

ValueAxis radiusAxis = new NumberAxis();
radiusAxis.setInverted(true);
//radiusAxis.setTickLabelsVisible(false);
…
plot.setAxisLocation(PolarAxisLocation.WEST_BELOW);
Image

Are you by chance altering the axisLocations themselves using setAxisLocation(int index, …)?

sildon
Posts: 6
Joined: Sat Sep 26, 2020 10:31 am
antibot: No, of course not.

Re: Polar Axis Location incorrect for West and South

Post by sildon » Tue Sep 29, 2020 6:19 am

No, I'm not using setAxisLocation(int index, …), I'm using plot.setAxisLocation(PolarAxisLocation.SOUTH_RIGHT); I notice your angle offset is 180, in my case I always have it at -90.
Below are images of what I'm seeing. First is normal/default. The second is applying setAxisLocation only. You'll notice the zero value as at the bottom. The third is the second with setInvert(true). Although this flips the values so that zero is centered, the yellow line has been altered.
Image
Image
Image

Just in case my attempt to link images didn't work, here are the url's to the images: https://www.dropbox.com/s/uepeugah46gfn ... h.png?dl=0 https://www.dropbox.com/s/q1ilgk0o22sh9 ... h.png?dl=0 https://www.dropbox.com/s/hk90y29llbgde ... t.png?dl=0

sildon
Posts: 6
Joined: Sat Sep 26, 2020 10:31 am
antibot: No, of course not.

Re: Polar Axis Location incorrect for West and South

Post by sildon » Tue Sep 29, 2020 8:35 am

I've managed to create a small program that shows the issue I'm seeing. I use invertAxis(true) for south & west, and invertAxis(false) for north & east. This maintains zero in the center but the data is flipped for invertAxis(true).

Code: Select all

package samplecode;

import java.awt.EventQueue;
import javax.swing.JFrame;
import org.jfree.ui.RefineryUtilities;

/**
 * @author 
 *
 */


public class SampleCode extends JFrame {
   static final Wind wind = new Wind("wind");


   static Thread startWindGraph() {
      final Thread updaterThread = wind.new updaterThread();

      EventQueue.invokeLater(new Runnable() {
         public void run() {
            wind.pack();
            wind.setSize(640, 460);
            RefineryUtilities.centerFrameOnScreen(wind);
            updaterThread.setDaemon(true);
            updaterThread.setName("updaterThread");
            updaterThread.start();
             wind.setVisible(true);
         }
      });
      return updaterThread;
   }

   public static void main(String[] args) {
    Thread watch =  startWindGraph();
   }
}

Code: Select all

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package samplecode;

import static java.lang.Thread.MIN_PRIORITY;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.PolarChartPanel;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTick;
import org.jfree.chart.plot.PolarAxisLocation;
import org.jfree.chart.plot.PolarPlot;
import org.jfree.chart.renderer.DefaultPolarItemRenderer;
import static org.jfree.chart.ui.TextAnchor.BOTTOM_CENTER;
import static org.jfree.chart.ui.TextAnchor.BOTTOM_LEFT;
import static org.jfree.chart.ui.TextAnchor.BOTTOM_RIGHT;
import static org.jfree.chart.ui.TextAnchor.CENTER_LEFT;
import static org.jfree.chart.ui.TextAnchor.CENTER_RIGHT;
import static org.jfree.chart.ui.TextAnchor.TOP_CENTER;
import static org.jfree.chart.ui.TextAnchor.TOP_LEFT;
import static org.jfree.chart.ui.TextAnchor.TOP_RIGHT;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;

/**
 *
 * @author Crew
 */
public class Wind extends ApplicationFrame {

   static XYSeries xySeries = new XYSeries("xy", false);

   static XYSeriesCollection xyCollection = new XYSeriesCollection();
   static DefaultPolarItemRenderer renderer = new DefaultPolarItemRenderer();
   static PolarPlot plot = new PolarPlot(xyCollection, null, renderer) {
      @Override
      protected List refreshAngleTicks() {
         List ticks = new ArrayList();
         ticks.add(new NumberTick(0, "N", BOTTOM_CENTER, BOTTOM_CENTER, 0));
         ticks.add(new NumberTick(45, "NE", BOTTOM_LEFT, BOTTOM_LEFT, 0));
         ticks.add(new NumberTick(90, "E", CENTER_LEFT, CENTER_LEFT, 0));
         ticks.add(new NumberTick(135, "SE", TOP_LEFT, TOP_LEFT, 0));
         ticks.add(new NumberTick(180, "S", TOP_CENTER, TOP_CENTER, 0));
         ticks.add(new NumberTick(225, "SW", TOP_RIGHT, TOP_RIGHT, 0));
         ticks.add(new NumberTick(270, "W", CENTER_RIGHT, CENTER_RIGHT, 0));
         ticks.add(new NumberTick(315, "NW", BOTTOM_RIGHT, BOTTOM_RIGHT, 0));

         return ticks;
      }
   };
   static JFreeChart chart = new JFreeChart("default", JFreeChart.DEFAULT_TITLE_FONT, plot, false);
   final static PolarChartPanel chartPanel = new PolarChartPanel(chart, false);

   private void getXYData() {

      xySeries.add(0, 0);
   }

   void getNewData() {
      double x = 0;
      double y =0;
      
      x = xySeries.getMaxX();
       x += 10;
      y=Math.toRadians(x)*10;
      
      xySeries.add(x, y);
   }

   public Wind(String title) {
      super(title);
      getXYData();

      plot.setDataset(xyCollection);
      plot.setRenderer(renderer);
      NumberAxis rangeAxis = new NumberAxis();
      xyCollection.addSeries(xySeries);//0
      rangeAxis.setAutoRange(false);
      rangeAxis.setUpperBound(15);
      plot.setAxis(rangeAxis);
      plot.setRadiusMinorGridlinesVisible(false);
      renderer.setConnectFirstAndLastPoint(false);

      final JFreeChart chart2 = ChartFactory.createPolarChart("chart2",
              xyCollection, true, false, false);
      PolarPlot plot2 = (PolarPlot) chart2.getPlot();
      plot2.setRenderer(renderer);
      setContentPane(chartPanel);

   }

   class updaterThread extends Thread {

      public void run() {
         setPriority(MIN_PRIORITY); // be nice
         PolarPlot realTimePlot = (PolarPlot) chart.getPlot();
         NumberAxis rangeAxis;
         rangeAxis = new NumberAxis();
         int i = 0;
         while (i<37) {
            try {
               getNewData();
               switch (i) {
                  case 0: {
                     realTimePlot.setAxisLocation(PolarAxisLocation.NORTH_RIGHT);
                     rangeAxis.setInverted(false);
                     break;
                  }
                  case 1: {
                     realTimePlot.setAxisLocation(PolarAxisLocation.EAST_ABOVE);
                     rangeAxis.setInverted(false);
                     break;
                  }
                  case 2: {
                     realTimePlot.setAxisLocation(PolarAxisLocation.SOUTH_RIGHT);
                     rangeAxis.setInverted(true);
                     break;
                  }
                  case 3: {
                     realTimePlot.setAxisLocation(PolarAxisLocation.WEST_ABOVE);
                     rangeAxis.setInverted(true);
                     break;
                  }
               }
               i++;
               if (i > 3) {
                  i = 0;
               }

               double scale = Math.ceil(xySeries.getMaxY());
               rangeAxis.setUpperBound(scale);
               realTimePlot.setAxis(rangeAxis);

               Thread.sleep(1000);
            } catch (InterruptedException ex) {
               Logger.getLogger(Wind.class.getName()).log(Level.SEVERE, null, ex);
            }
         }
      }
   }
}

John Matthews
Posts: 513
Joined: Wed Sep 12, 2007 3:18 pm

Re: Polar Axis Location incorrect for West and South

Post by John Matthews » Tue Sep 29, 2020 5:21 pm

Ah, I see; I've always used setAxisLocation in conjunction with a corresponding setAngleOffset. It looks like you want to stay north up and label the axis closest to a principal wind. I'm not sure I know how to fix the problem. I migrated your SampleCode to v1.5 with a similar result. As an aside, I'm wary of updating the chart panel from a thread other the event dispatch thread; I typically use SwingWorker in this context.

sildon
Posts: 6
Joined: Sat Sep 26, 2020 10:31 am
antibot: No, of course not.

Re: Polar Axis Location incorrect for West and South

Post by sildon » Wed Sep 30, 2020 4:18 am

If I'm reading you correctly, I can not do what I want using setAxisLocation for the foreseeable future.
One option I'm thinking of, but not sure it'll be worth the time and trouble, is to overlay another polar plot on top of this one where the top plot will have the axis values and the bottom plot will show the data.
Anyway, thanks for confirming that I wasn't using setAxisLocation improperly.

John Matthews
Posts: 513
Joined: Wed Sep 12, 2007 3:18 pm

Re: Polar Axis Location incorrect for West and South

Post by John Matthews » Wed Sep 30, 2020 5:09 pm

An alternative, if I infer correctly, might include a chart Annotation, e.g. XYShapeAnnotation or XYDrawableAnnotation, to indicate direction.

sildon
Posts: 6
Joined: Sat Sep 26, 2020 10:31 am
antibot: No, of course not.

Re: Polar Axis Location incorrect for West and South

Post by sildon » Thu Oct 01, 2020 12:51 am

I'm confused. I thought the only annotation for polar charts were the text annotation in the lower right corner. Could you point to some examples using XYShapeAnnotations and XYDrawableAnnotation on a polar chart?

John Matthews
Posts: 513
Joined: Wed Sep 12, 2007 3:18 pm

Re: Polar Axis Location incorrect for West and South

Post by John Matthews » Thu Oct 01, 2020 9:06 am

Sadly, no. You are correct.

Locked