Map grid possible, X=Y always?

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
schultjd
Posts: 3
Joined: Sat May 02, 2009 2:00 pm

Map grid possible, X=Y always?

Post by schultjd » Sat May 02, 2009 2:09 pm

Is it possible to create an XY plot with the x and y axes always equal no matter how the user zooms? That is, honor the longest requested length for the zoom and then create a square area from this longest length. The main thing is that the "chart" actually honor a square grid where 1 unit in x always equals 1 unit it y (a standard UTM coordinate grid system for a map). JFreeChart has everything esle for a simple map, we just need to be able to FIX the mapping units to 1x = 1y. Seems simple, maybe I've overlooked the obvious. Any comments appreciated.

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

Re: Map grid possible, X=Y always?

Post by david.gilbert » Mon May 04, 2009 3:17 pm

Unfortunately it is not simple. But it is one of the problems that I want to solve, so we can support map plots. I have done some work on this previously, but I'm unlikely to get back onto it until at least after JavaOne.
David Gilbert
JFreeChart Project Leader

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

dnater
Posts: 3
Joined: Tue Mar 08, 2011 7:06 pm
antibot: No, of course not.

Re: Map grid possible, X=Y always?

Post by dnater » Tue Mar 08, 2011 7:18 pm

Hello,

I'd like to add my vote for the equivalent of Matlab's "axis equal" feature for plots. I intended to use JFreeChart for plotting geographic information but the inability to ensure that the X and Y axes have the same scale (e.g. N-pixels/meter) is a show stopper. I even paid for the developer guide.

I have read all the threads related to this issue that I can find, but I have not yet been able to make any of the solutions suggested (such as that by aiello from Oct. 2007) work in my context.

According to Mr. Gilbert, the primary obstacle to a general solution seems to be plots with multiple axes. For most geographic data, I don't think that is an issue. Perhaps there could be a MapPlot extension to XYPlot that only supports one pair of axes that are squared off by default?

xyzPlotter
Posts: 1
Joined: Wed Jun 01, 2011 11:26 am
antibot: No, of course not.

Re: Map grid possible, X=Y always?

Post by xyzPlotter » Wed Jun 01, 2011 11:29 am

I haven't tried it yet but just found someone who claims to have created a fix.

http://www.xspace.org/Other/index.html

pfxo
Posts: 7
Joined: Thu Sep 22, 2011 3:15 am
antibot: No, of course not.

Re: Map grid possible, X=Y always?

Post by pfxo » Fri Sep 23, 2011 2:58 am

xyzPlotter wrote:I haven't tried it yet but just found someone who claims to have created a fix.

http://www.xspace.org/Other/index.html
This unfortunately not worked for me. So, I have writtem another possible solution for squared XYPlot in scala code:

Code: Select all

package org.jfreex
package chart.plot

import java.awt.Graphics2D

import java.awt.geom. {

  Point2D,
  Rectangle2D

}

import org.jfree.chart.axis.AxisSpace

import org.jfree.chart.plot. {

  Plot,
  PlotRenderingInfo,
  PlotState,
  XYPlot

}

/** Extends [[org.jfree.chart.plot.XYPlot]] with squared and expandable axis.
 *
 * @author pfxo
 */
trait ExtendedXYPlot extends XYPlot {

  var squared = true
  var expandable = true

  override def draw(g2: Graphics2D,
                    area: Rectangle2D,
                    anchor: Point2D,
                    parentState: PlotState,
                    info: PlotRenderingInfo) {

    // XYPlot part.
    if(area.getWidth <= Plot.MINIMUM_WIDTH_TO_DRAW ||
       area.getHeight <= Plot.MINIMUM_HEIGHT_TO_DRAW)
      return

    val clonedArea = area.clone.asInstanceOf[Rectangle2D]
    getInsets.trim(clonedArea)

    val method = classOf[XYPlot].getDeclaredMethod("calculateAxisSpace",
                                                   classOf[Graphics2D],
                                                   classOf[Rectangle2D])
    method.setAccessible(true)
    val dataArea = method.invoke(this, g2, clonedArea).asInstanceOf[AxisSpace].shrink(clonedArea, null)

    getAxisOffset.trim(dataArea)

    if(dataArea.isEmpty)
      return

    if(expandable) {

      // Expandable X Axis.
      if(lastDataArea.width != dataArea.getWidth) {

        if(lastDataArea.width != -1.0 &&
           lastDataArea.domainLength != -1.0)
          getDomainAxis.setRange(
            new org.jfree.data.Range(
              getDomainAxis.getLowerBound,
              getDomainAxis.getLowerBound + lastDataArea.domainLength /
              lastDataArea.width * dataArea.getWidth), false, false)

        lastDataArea.width = dataArea.getWidth
        lastDataArea.domainLength = getDomainAxis.getRange.getLength

      } else if(lastDataArea.domainLength != getDomainAxis.getRange.getLength)
        lastDataArea.domainLength = getDomainAxis.getRange.getLength

      // Expandable Y Axis.
      if(lastDataArea.height != dataArea.getHeight) {

        if(lastDataArea.height != -1.0 &&
           lastDataArea.rangeLength != -1.0)
          getRangeAxis.setRange(
            new org.jfree.data.Range(
              getRangeAxis.getLowerBound,
                getRangeAxis.getLowerBound + lastDataArea.rangeLength /
                lastDataArea.height * dataArea.getHeight), false, false)

        lastDataArea.height = dataArea.getHeight
        lastDataArea.rangeLength = getRangeAxis.getRange.getLength

      } else if(lastDataArea.rangeLength != getRangeAxis.getRange.getLength)
        lastDataArea.rangeLength = getRangeAxis.getRange.getLength

    }

    // Square Y axis to X axis.
    if(squared &&
       getDomainAxis.getRange.getLength /
       dataArea.getWidth *
       dataArea.getHeight != getRangeAxis.getRange.getLength) {

      getDomainAxis.setRange(
        new org.jfree.data.Range(
          getDomainAxis.getLowerBound,
          getDomainAxis.getLowerBound +
          getRangeAxis.getRange.getLength /
          dataArea.getHeight * dataArea.getWidth), false, false)

      lastDataArea.domainLength = getDomainAxis.getRange.getLength

    }

    super.draw(g2, area, anchor, parentState, info)

  }


  // Last data.
  private object lastDataArea {

    var width: Double = -1.0
    var height: Double = -1.0
    var domainLength: Double = -1.0
    var rangeLength: Double = -1.0

  }
}
This ExtendedXYPlot treat is simple to use:

Code: Select all

val plot = new XYPlot(myDataset, xAxis, yAxis, renderer) with ExtendedXYPlot
Now, your plot has squares and is expandable (see this thread for explanation what's a expandable plot). I don't know whether this ExtendedXYPlot work for all, because I just tested with XYBlockRenderer and DefaultXYZDataset to create a Point and Figure chart.

Locked