How to use different shapes to distinguish lines

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
prolaznik22
Posts: 11
Joined: Fri Feb 03, 2006 9:27 pm

How to use different shapes to distinguish lines

Post by prolaznik22 » Sat Jul 08, 2006 1:36 pm

Hi,

I am using the latest JFreeChart. In my line graph, I want each line to start and end with some shape. I did some research in the news group and I found that I have to implement my own renderer to do this.

So, My questions are:

1) How would I start about doing this?

2)I already noticed that Jfreechart puts different shapes on the lines.Where does Jfreechart get these shapes?

skunk
Posts: 1087
Joined: Thu Jun 02, 2005 10:14 pm
Location: Brisbane, Australia

Post by skunk » Sat Jul 08, 2006 2:35 pm

2.

Code: Select all

org.jfree.chart.plot.DefaultDrawingSupplier

prolaznik22
Posts: 11
Joined: Fri Feb 03, 2006 9:27 pm

Solved the problem

Post by prolaznik22 » Sun Jul 09, 2006 1:28 am

Thanks skunk for your reply.

Basically, what I did was that I implemented my renderer that extends XYLineAndShapeRenderer. I overrode drawSecondPass ( a protected method which is responsibly for drawing shapes) and I put my logic in that method.

The code is:

Code: Select all

package com.telus.insight.graph;

import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;

import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.plot.CrosshairState;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.RectangleEdge;
import org.jfree.util.PublicCloneable;
import org.jfree.util.ShapeUtilities;

public class CustomXYLineAndShapeRenderer extends XYLineAndShapeRenderer 
implements PublicCloneable,Serializable,Cloneable,XYItemRenderer {
	
	private HashMap markedPointsPerSeries;
	private ArrayList shapes;
	
	CustomXYLineAndShapeRenderer(HashMap markedPointsPerSeries, ArrayList shapes) {
		super();
		this.markedPointsPerSeries = markedPointsPerSeries;
		this.shapes = shapes;
	}
	
	private boolean markItem (int series, int item) {
		
		
		//System.err.println("Entering markItem, series is "  + series);
		ArrayList pointsToBeMarked = 
		(ArrayList)markedPointsPerSeries.get(new Integer(series));
		
		if (pointsToBeMarked != null) {
		  int firstItem = ((Integer)pointsToBeMarked.get(0)).intValue();
		  int secondItem = ((Integer)pointsToBeMarked.get(1)).intValue();
		  //System.err.println("firstItem is "+ firstItem);
		  //System.err.println("secondItem is " + secondItem);
		
		  if (item == firstItem || item == secondItem)
			 return true;
		}
		
	 	//System.err.println("Exiting markItem");
		return false;
		
	}
	
	protected void drawSecondaryPass
    (Graphics2D g2, XYPlot plot,XYDataset dataset,int pass, int series, int item,
     ValueAxis domainAxis,Rectangle2D dataArea,ValueAxis rangeAxis,CrosshairState crosshairState,
     EntityCollection entities) {

	Shape entityArea = null;
	boolean drawShape = markItem(series,item);
	
	// get the data point...
	double x1 = dataset.getXValue(series, item);
	double y1 = dataset.getYValue(series, item);
	
	if (Double.isNaN(y1) || Double.isNaN(x1)) {
	  return;
	}
	
	PlotOrientation orientation = plot.getOrientation();
	RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
	RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
	double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation);
	double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation);
	
    double dataAreaX = dataArea.getX();
    double dataAreaY = dataArea.getY();
    
   
	
	if (drawShape) {
    
		System.err.println("Series is " + series + " item is " + item);
		System.err.println("transX1 is " + transX1 + " transY1 is " +  transY1);
		System.err.println("dataAreaX is " + dataAreaX + " dataAreaY is " + dataAreaY);
			  	
	  Shape shape = (Shape)shapes.get(series);
	if (orientation == PlotOrientation.HORIZONTAL) {
	  shape = ShapeUtilities.createTranslatedShape(shape, transY1, transX1);
	}
	
	else if (orientation == PlotOrientation.VERTICAL) {
	  shape = ShapeUtilities.createTranslatedShape(shape, transX1, transY1);
	}

	entityArea = shape;
	
	if (shape.intersects(dataArea)) {
	  if (getItemShapeFilled(series, item)) {
	    if (super.getUseFillPaint()) {
	      g2.setPaint(getItemFillPaint(series, item));
	}
	else {
	   g2.setPaint(getItemPaint(series, item));
	}
	g2.fill(shape);
	}
	if (super.getDrawOutlines()) {
	  if (getUseOutlinePaint()) {
	   g2.setPaint(getItemOutlinePaint(series, item));
	  }
    else {
	   g2.setPaint(getItemPaint(series, item));
	}
  	 g2.setStroke(getItemOutlineStroke(series, item));
	 g2.draw(shape);
	}
	}
	}
	
	// draw the item label if there is one...
	if (isItemLabelVisible(series, item)) {
	  double xx = transX1;
	  double yy = transY1;
	  if (orientation == PlotOrientation.HORIZONTAL) {
	    xx = transY1;
	    yy = transX1;
	  }          
	  drawItemLabel(g2, orientation, dataset, series, item, xx, yy,(y1 < 0.0));
	}
	
	updateCrosshairValues
	(crosshairState, x1, y1, transX1, transY1, plot.getOrientation());
	
	// add an entity for the item...
	if (entities != null) {
	  addEntity(entities, entityArea, dataset, series, item, transX1, transY1);
	}
   }
	
}

Locked