What's wrong with my bubble chart? ImageMaps ?

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
msatish
Posts: 4
Joined: Wed Jun 14, 2006 4:51 pm

What's wrong with my bubble chart? ImageMaps ?

Post by msatish » Fri Oct 19, 2007 4:02 am

I want to generate ImageMaps for a BubbleChart. I want to make the Bubbles Clickable for Drill-Down. How do i do that??
Here's the code for my example.

I see that the image map is generated but is returned empty, How do i ensure that a image-map is generated for XYZDataset?


Any tutorial that shows ImageMaps/URLs/ToolTips generated for a Bubble Chart? Plz help me out



Code: Select all

/* JSP Page */
<%@ page import = "testchart.*" %>
<%@ page import = "java.io.PrintWriter" %>
<%@ page import = "java.util.ArrayList" %>
<%@ page import = "java.util.Iterator" %>

<%
	String filename = ChartGen.generateBubbleChart(session, new PrintWriter(out));
	String graphURL = request.getContextPath() + "/servlet/DisplayChart?filename=" + filename;
%>
<html>
<head>
<link rel="stylesheet" href="sample.css" type="text/css"/>
<title>Bubble Sample</title>
</head>
<body>



	<img src="<%= graphURL %>" width=800 height=600 border=0 usemap="#<%= filename %>">

</body>
</html>

/* ---------------------------------------------------------------------- */
/* Code for the ChartGen class */

public class ChartGen {
	
	 
	public static String generateBubbleChart(HttpSession session,PrintWriter pw) {
		
		String filename = null;
		List<RowItem> data;
		try {
			
        // This generates random data stored in List
	RowGenerator s = new RowGenerator();
    data = s.getResults();

			XYZDataset dataset = new XYZData();
			XYZSeries series = new XYZSeries("Bubbles");
			
			for(RowItem row :data) {
				series.addData(row.getPerformance(), row.getPerformanceBPT(), row.getDeviation()/10);
				System.out.println(" TEST" +row.getPerformance()+" "+ row.getPerformanceBPT() +" "+ (row.getDeviation()/10));
			}
			
			((XYZData)dataset).addSeries(series);
			
			
			System.out.println(dataset.getSeriesCount());
			
			String xval = dataset.getSeriesKey(0).toString();
			//String yval = dataset.getSeriesKey(0).toString();
			
			JFreeChart chart = ChartFactory.createBubbleChart("Flex", xval,"yval", dataset, PlotOrientation.VERTICAL, true, true, true);
			
			ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection());
            filename = ServletUtilities.saveChartAsPNG(chart, 800,600, session);
            ChartUtilities.writeImageMap(pw, filename, info, false);
            pw.flush();
 }

/* -------------------------------------------------------------------------------- */

/* XYZ Data */
package testchart;

import java.util.Vector; 

import org.jfree.data.xy.AbstractXYZDataset;
import org.jfree.data.xy.XYZDataset;

public class XYZData extends AbstractXYZDataset implements XYZDataset{

	 private Vector seriesTable = new Vector();
	 private int seriesCount = 0;

	 /**
	 * This method adds a serie to the dataset.
	 *
	 * @param serie the serie to be added.
	 */
	 public void addSeries(XYZSeries serie) {
	 seriesTable.addElement((Object) serie);
	 seriesCount++;
	 }


	 /**
	 * Returns the number of series in the dataset.
	 *
	 * @return the series count.
	 */
	 public int getSeriesCount() {
	 return seriesCount;
	 }

	 /**
	 * Returns the name of a series.
	 *
	 * @param series the series (zero-based index).
	 *
	 * @return the name of the series.
	 */
	 public String getSeriesName(int series) {
	 return ((XYZSeries)seriesTable.get(series)).getName();
	 }

	 /**
	 * Returns the number of items in a series.
	 *
	 * @param series the series (zero-based index).
	 *
	 * @return the number of items within the series.
	 */
	 public int getItemCount(int series) {
	 return ((XYZSeries)this.seriesTable.get(series)).getLenght();
	 }

	 /**
	 * Returns the x-value for an item within a series.
	 * <P>
	 * The implementation is responsible for ensuring that the x-values are
	 * presented in ascending order.
	 *
	 * @param series the series (zero-based index).
	 * @param item the item (zero-based index).
	 *
	 * @return the x-value.
	 */
	 public double getXValue(final int series, final int item) {
	 return new Double(((XYZSeries)this.seriesTable.get(series)).getX(item));
	 }

	 /**
	 * Returns the x-value for an item within a series.
	 * <P>
	 * The implementation is responsible for ensuring that the x-values are
	 * presented in ascending order.
	 *
	 * @param series the series (zero-based index).
	 * @param item the item (zero-based index).
	 *
	 * @return the x-value.
	 */
	 public  Number getX(final int series, final int item) {
	 return ((XYZSeries)this.seriesTable.get(series)).getX(item);
	 }

	 /**
	 * Returns the y-value for an item within a series.
	 *
	 * @param series the series (zero-based index).
	 * @param item the item (zero-based index).
	 *
	 * @return the y-value.
	 */
	 public double getYValue(final int series, final int item) {
	 return new Double(((XYZSeries)this.seriesTable.get(series)).getY(item));
	 }

	 /**
	 * Returns the y-value for an item within a series.
	 * <P>
	 * The implementation is responsible for ensuring that the y-values are
	 * presented in ascending order.
	 *
	 * @param series the series (zero-based index).
	 * @param item the item (zero-based index).
	 *
	 * @return the y-value.
	 */
	 public Number getY(final int series, final int item) {
	 return ((XYZSeries)this.seriesTable.get(series)).getY(item);
	 }

	 /**
	 * Returns the z-value for the specified series and item.
	 *
	 * @param series the series (zero-based index).
	 * @param item the item (zero-based index).
	 *
	 * @return the z-value for the specified series and item.
	 */
	 public double getZValue(final int series, final int item) {
	 return new Double(((XYZSeries)this.seriesTable.get(series)).getZ(item));
	 }

	 /**
	 * Returns the z-value for an item within a series.
	 * <P>
	 * The implementation is responsible for ensuring that the z-values are
	 * presented in ascending order.
	 *
	 * @param series the series (zero-based index).
	 * @param item the item (zero-based index).
	 *
	 * @return the z-value.
	 */
	 public Number getZ(final int series, final int item) {
	 return ((XYZSeries)this.seriesTable.get(series)).getZ(item);
	 }


	@Override
	public Comparable getSeriesKey(int series) {
		// TODO Auto-generated method stub
		return null;
	}



}

/*--------------------------------------------------------------------------------*/
/* XYZSeries.java */

package testchart;

import java.util.Vector;

public class XYZSeries {

	/** The name of the serie. */
	private String name;

	/** The x values. */
	private Vector xVal = new Vector();

	/** The y values. */
	private Vector yVal = new Vector();

	/** The z values. */
	private Vector zVal = new Vector();

	public XYZSeries(String name) {
	this.name = name;
	}

	/**
	* This method add an XYZ coordinate to the serie.
	*
	* @param x the x coordinate
	* @param y the y coordinate
	* @param z the z coordinate
	*/
	public void addData(double x, double y, double z) {
	xVal.addElement(new Double(x));
	yVal.addElement(new Double(y));
	zVal.addElement(new Double(z));
	}

	/**
	* This method clears all date added to the serie.
	*
	*/
	public void clear() {
	xVal.clear();
	yVal.clear();
	zVal.clear();
	}

	/**
	*
	* @return the name of the serie
	*/
	public String getName() {
	return this.name;
	}

	public int getLenght() {
	return xVal.size();
	}

	/**
	*
	* @param position (zero-based index)
	* @return the value of the x coordinate
	*/
	public double getX(int position) {
	return ((Double) xVal.get(position)).doubleValue();
	}

	/**
	*
	* @param position (zero-based index)
	* @return the value of the y coordinate
	*/
	public double getY(int position) {
	return ((Double) yVal.get(position)).doubleValue();
	}

	/**
	*
	* @param position (zero-based index)
	* @return the value of the z coordinate
	*/
	public double getZ(int position) {
	return ((Double) zVal.get(position)).doubleValue();
	}

	}




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

Post by david.gilbert » Fri Oct 19, 2007 2:39 pm

The demo below creates a chart image (PNG) and a corresponding HTML file with the HTML image map included. You can run it locally, and open the HTML file in your browser to see that it works.

After that, you need to make it work on your server for clients that access it remotely...looks like you're using JSP, but that's outside my area of expertise so I can't tell you what you might or might not be doing wrong there.

Code: Select all

/* ------------------
 * ImageMapDemo8.java
 * ------------------
 * (C) Copyright 2007, by Object Refinery Limited.
 *
 */

package demo;

import java.awt.Color;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.entity.StandardEntityCollection;
import org.jfree.chart.imagemap.ImageMapUtilities;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.DefaultXYZDataset;
import org.jfree.data.xy.XYZDataset;

/**
 * A demo showing how to create an HTML image map for a bubble chart.
 */
public class ImageMapDemo8 {

    /**
     * Default constructor.
     */
    public ImageMapDemo8() {
        super();
    }

    /**
     * Creates a chart.
     * 
     * @param dataset  the dataset.
     * 
     * @return The chart.
     */
    private static JFreeChart createChart(XYZDataset dataset) {
        JFreeChart chart = ChartFactory.createBubbleChart(
                "Bubble Chart Demo 1", "X", "Y", dataset, 
                PlotOrientation.HORIZONTAL, true, true, true);
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setForegroundAlpha(0.65f);
        
        XYItemRenderer renderer = plot.getRenderer();
        renderer.setSeriesPaint(0, Color.blue);
        
        // increase the margins to account for the fact that the auto-range 
        // doesn't take into account the bubble size...
        NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis();
        domainAxis.setLowerMargin(0.15);
        domainAxis.setUpperMargin(0.15);
        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setLowerMargin(0.15);
        rangeAxis.setUpperMargin(0.15);
        return chart;
    }
    
    /**
     * Creates a sample dataset.
     * 
     * @return A sample dataset.
     */
    public static XYZDataset createDataset() {
        DefaultXYZDataset dataset = new DefaultXYZDataset(); 
        double[] x = {2.1, 2.3, 2.3, 2.2, 2.2, 1.8, 1.8, 1.9, 2.3, 3.8};
        double[] y = {14.1, 11.1, 10.0, 8.8, 8.7, 8.4, 5.4, 4.1, 4.1, 25};
        double[] z = {2.4, 2.7, 2.7, 2.2, 2.2, 2.2, 2.1, 2.2, 1.6, 4};
        double[][] series = new double[][] { x, y, z };
        dataset.addSeries("Series 1", series);
        return dataset;
    }

    /**
     * Starting point for the demo.
     *
     * @param args  ignored.
     */
    public static void main(String[] args) {

        JFreeChart chart = createChart(createDataset());

        // save it to an image
        try {
            ChartRenderingInfo info = new ChartRenderingInfo(
                    new StandardEntityCollection());
            File file1 = new File("bubble100.png");
            ChartUtilities.saveChartAsPNG(file1, chart, 600, 400, info);

            // write an HTML page incorporating the image with an image map
            File file2 = new File("bubble100.html");
            OutputStream out = new BufferedOutputStream(new FileOutputStream(
                    file2));
            PrintWriter writer = new PrintWriter(out);
            writer.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"");
            writer.println("\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
            writer.println("<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">");
            writer.println("<head><title>JFreeChart Image Map Demo 8</title></head>");
            writer.println("<body><p>");
            ImageMapUtilities.writeImageMap(writer, "chart", info);
            writer.println("<img src=\"bubble100.png\" "
                           + "width=\"600\" height=\"400\" usemap=\"#chart\" alt=\"bubble100.png\"/>");
            writer.println("</p></body>");
            writer.println("</html>");
            writer.close();

        }
        catch (IOException e) {
            e.printStackTrace();
        }

    }

}
David Gilbert
JFreeChart Project Leader

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

msatish
Posts: 4
Joined: Wed Jun 14, 2006 4:51 pm

But how do i use a dynamic array?

Post by msatish » Fri Oct 19, 2007 3:42 pm

Dave.

Thanks for the reply.

the demo uses arrays with pre-defined sizes and populated..how can i use a dynamic array???

Code: Select all


DefaultXYZDataset dataset = new DefaultXYZDataset();
        double[] x = {2.1, 2.3, 2.3, 2.2, 2.2, 1.8, 1.8, 1.9, 2.3, 3.8};
        double[] y = {14.1, 11.1, 10.0, 8.8, 8.7, 8.4, 5.4, 4.1, 4.1, 25};
        double[] z = {2.4, 2.7, 2.7, 2.2, 2.2, 2.2, 2.1, 2.2, 1.6, 4};
        double[][] series = new double[][] { x, y, z };
        dataset.addSeries("Series 1", series);
        return dataset; 

How can i populate the x, y, z dynamically?

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

Post by david.gilbert » Fri Oct 19, 2007 3:54 pm

DefaultXYZDataset is not the most flexible implementation of the XYZDataset that is possible, but it's all we have for now. If you come up with another implementation that allows (x, y, z) items to be added dynamically, a patch would be very welcome!
David Gilbert
JFreeChart Project Leader

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

Locked