I'm trying out Protovis-Java (
http://mbostock.github.com/protovis/protovis-java/) for generating nice little charts. Since Protovis-Java uses JOGL I hoped to integrate the charts into the Processing rendering context.
Has anybody an idea how I could realize that? Protovis-Java uses a GLDisplay object that I try to use inside Processing.
//params int N = 100, w = 500, h = 200; // sizing parameters
// generate a list of data elements // we use a one element array so we can update the value final List<int[]> data = new ArrayList<int[]>(); for (int i=0; i<N; ++i) { data.add(new int[]{(int)(1 + 100*Math.random())}); }
// -- vis ---
// create the visualization scene final Scene vis = new Scene(); vis.top(10).left(10).width(w).height(h);
// Define property bundles to define how items should // (a) enter the scene: how to initialize newly visible elements // (b) exit the scene: how removed elements should disappear // Note that be default, elements animate to/from alpha=0 // To change this, one must define the alpha property Mark enter, exit;
// new elements will 'grow' out of the baseline enter = Mark.create() .left("{{item.left + 5}}") .bottom(0) .height(0) .width(0) ; // exiting elements will 'shrink' into the baseline exit = Mark.create() .left("{{item.left - 3}}") .bottom("{{item.bottom}}") .height(0) .width(0) ;
// // new elements will drop in from the sky // enter = Mark.build() // .left("{{item.left + 5}}") // .bottom(h) // ; // // exiting elemtns will 'blow up' as they fade out // exit = Mark.build() // .left("{{item.left - 3 - 5}}") // .bottom("{{item.bottom - 5}}") // .width("{{item.width + 10}}") // .height("{{item.height + 10}}") // ;
// Show data as a simple bar chart vis.add(MarkType.Bar) .def("i", -1) .data(data).datatype(int[].class) .key("{{data.hashCode()}}") .left("{{index*5}}") .height("{{data[0]}}") .bottom(0) .width(3) .fill("{{Fill.solid(i==index ? 0xff0000 : 0x1f27b4)}}") .delay("{{0.005*index}}") // determine animation delay .ease(Easing.Poly(2.2)) // determine animation style (easing) .enter(enter) .exit(exit) .mouseEnter("{{i(index).update()}}") .mouseExit("{{i(-1).update()}}");
vis.update();
// -- display stuff ---
Display display = new GLDisplay(); display.setSize(w+20, h+20); display.addScene(vis);
I have been experimenting for about a week with Processing for Information Visualization and I'm very impressed with the results after a few evening hours.
My aim is to combine a 2D or even 3D warehouse visualization (very individual) with small charts (very standard like bar charts, line charts, sparklines) that get the dataset from a JDBC database. Now I'm stuck with integrating the output from JFreeChart into the 3D (OPENGL) context.
I've already managed to integrate a chart as BufferedImage like in this code snippet:
//Add jcommon-1.0.17.jar and jfreechart-1.0.14.jar to files (folder 'code')
JFreeChart chart; PImage chartImage;
void setup(){ size(300, 300);
// create a dataset the chart is generated from DefaultPieDataset dataset = new DefaultPieDataset(); dataset.setValue("Processing", new Integer(75)); dataset.setValue("Other", new Integer(25));
// create the chart from dataset and adjust visualization chart = ChartFactory.createPieChart(null, dataset, false, true, false); chart.setBorderVisible(false); chart.setBackgroundPaint(java.awt.Color.white) ; chart.removeLegend(); chart.setAntiAlias(true); chart.setBorderPaint(java.awt.Color.white);
In OPENGL it shows up but of course as bitmap image. The GUI already offers a handle for scaling the drawing. Because the warehouse map is loaded as SVG image there's no distortion when scaling to a maximum level. In contrast the chart gets very pixelated.
Ok - I could generate a 5000 x 5000 px image and then scale it down.... hmmm...
So I'm wondering: Why at all transforming the JAVA2D objects into a BufferedImage instead of drawing directly into the graphics/rendering context of Processing? With perfect quality as vector graphic. How could I do that?
At the moment I'm experimenting with JAVA2D objects and Batik/SVG. Please see the extended code here:
JFreeChart chart; PImage chartImage; PShape s; SVGGraphics2D svg; PGraphics pg; //PGraphicsJava2D pgj; - alternative for PGraphics?
void setup(){ size(300, 300);
// create a dataset the chart is generated from DefaultPieDataset dataset = new DefaultPieDataset(); dataset.setValue("Processing", new Integer(75)); dataset.setValue("Other", new Integer(25));
// create the chart from dataset chart = ChartFactory.createPieChart(null, dataset, false, true, false); chart.setBorderVisible(false); chart.setBackgroundPaint(java.awt.Color.white) ; chart.removeLegend(); chart.setAntiAlias(true); chart.setBorderPaint(java.awt.Color.white);
// create image from chart chartImage = new PImage(chart.createBufferedImage(300,300));
// SVG approach
// Get a DOMImplementation and create an XML document DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation(); Document document = domImpl.createDocument(null, "svg", null);
// Create an instance of the SVG Generator svg = new SVGGraphics2D(document);
// draw the chart in the SVG generator chart.draw(svg, new Rectangle2D.Double(0, 0, 400, 300), null);
//use PShape - not possible //s = svg;
// JAVA2D approach
pg = createGraphics(80, 80, P3D);
}
void draw(){
// original BufferedImage approach - SUCCESS // display chart image on screen image(chartImage, 0, 0);
// SVG approach - FAILED
//shape(s,0,0,30,30); - not possible to cast
//JAVA2D approach - FAILED
pg.beginDraw(); //chart.draw( pg, new Rectangle2D.Double(0, 0, 400, 300)); - not possible to cast pg.endDraw();
image(pg,50,50); }
I know that this is some kind of trial and error. If somebody could please give me a hint I'll dive into further ressources.