Adding support for triangular diagrams - input welcome

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
sammen
Posts: 15
Joined: Mon Feb 02, 2009 9:55 am

Adding support for triangular diagrams - input welcome

Post by sammen » Mon Feb 02, 2009 2:44 pm

I work in a scientific field where it is very common to visualize some calculation results in the form of Triangular/Ternary diagrams. (Here I had some URLs to information about such diagrams, but I was not allowed to post them. Look up "Ternary plot" on the English Wikipedia for examples of how they look and are constructed). Basically it is a diagram with three axes forming a triangle, but where the third value is dependent on the other two.

I believe this plot type is not currently supported, and I am thinking about adding it (if it's not a ridiculous amount of work). While I read up on the source code and the Developer's Guide I thought I'll just paste my thoughts here, and perhaps get some valuable hints from you guys who already know the code. Perhaps you can point me in the right direction and also tell me if I'm approaching something too challenging for a not yet so skilled Java developer.

I'm currently thinking that it's very similar to an XYPlot, and I will start to see what will have to be changed in order to fit in a triangular clipping area and rotated y-axis. Sounds easy, but is it? :)

/Sam

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 » Mon Feb 02, 2009 9:42 pm

I think it will be easy enough if the three axes don't need value labels (the examples at Wikipedia didn't have them). The problem with the labels is that the NumberAxis class assumes that it will have either a horizontal or vertical orientation. Aside from that, you'll just need a TernaryPlot class, some form of TernaryDataset interface (ideally with a default implementation) and maybe the plot should use a renderer abstraction (I don't know enough about this plot type to know if there are many rendering variations).

I'd encourage you to have a go at it, even if your Java skills are light (bear in mind that JFreeChart is my *first* Java program, so my own Java skills were very light when I started...and I'm still learning!).

I will try to help you...either keep posting in this thread, or use the JFreeChart developers mailing list.
David Gilbert
JFreeChart Project Leader

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

sammen
Posts: 15
Joined: Mon Feb 02, 2009 9:55 am

Post by sammen » Tue Feb 10, 2009 3:31 pm

David, thanks for your reply.

Value labels will indeed be necessary, I didn't notice that the examples I gave don't have any.

Ternary diagrams are a special type of XYPlots, but with transformed coordinates. I don't think it will be necessary to use a new type of dataset, the ones for XYPlots should do fine. The values that are plotted are still the same as in a cartesian coordinate system but they are represented differently. This type of diagram is a bit strange, but for some cases they are superior to using cartesian plots. For others they don't make sense at all.

In slightly other words; there is nothing triangular about the values that are to be plotted, they are just plotted in a triangular diagram by transforming them with some simple geometrical equations. Thinking about that, and regarding the difficulty you mentioned with the labels. Given that the labeling assumes rectangular shapes, why not use the same transformation for their location, as for the data points?

sammen
Posts: 15
Joined: Mon Feb 02, 2009 9:55 am

Re: Adding support for triangular diagrams - input welcome

Post by sammen » Wed Mar 04, 2009 4:01 pm

Most of my time on this has been spent trying to learn Java :), how JFreeChart is written and how I should incorporate the triangular support. I have done some very very basic stuff so far, before I ran into a little trouble.

My approach is that the triangular diagrams are nothing but XYPlots. So I added:

XYPlot field

Code: Select all

    /**
     * True if triangular XYPlot should be drawn
     */
    private boolean ternaryPlot = false;
If it is ternary I want to change the coordinates for the values. I take the calculated coordinates and transform them further:

XYLineAndShapeRenderer.drawPrimaryLine(...)

Code: Select all

       double transX0 = domainAxis.valueToJava2D(x0, dataArea, xAxisLocation);
        double transY0 = rangeAxis.valueToJava2D(y0, dataArea, yAxisLocation);
        
        if (plot.isTernary()) {
            transX0 = domainAxis.transXValueToTriangular(transX0, transY0, dataArea);
            transY0 = rangeAxis.transYValueToTriangular(transY0, dataArea);
        }


        double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation);
        double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation);

        if (plot.isTernary()) {
            transX1 = domainAxis.transXValueToTriangular(transX1, transY1, dataArea);
            transY1 = rangeAxis.transYValueToTriangular(transY1, dataArea);
        }

This is just the transform:

ValueAxis methods

Code: Select all

     /**
     * Converts a regular Java2D x coordinate to triangular
     * @param xCoord the regular Java2D x coordinate.
     * @param yCoord the regular Java2D y coordinate.
     * @param area  the area for plotting the data.
     *
     * @return The Java2D triangular x coordinate.
     *
     */
    public double transXValueToTriangular(double xCoord, double yCoord, Rectangle2D area) {
        double xOrigin = area.getMaxX();
        double yOrigin = area.getMaxY();
        return xCoord + (yOrigin - yCoord)*0.5;
    }

    /**
     * Converts a regular Java2D y coordinate to triangular
     * @param yCoord the regular Java2D y coordinate.
     * @param area  the area for plotting the data.
     *
     * @return The Java2D triangular y coordinate.
     *
     */
     public double transYValueToTriangular(double yCoord, Rectangle2D area) {

        double yOrigin = area.getMaxY();
        return yOrigin - (yOrigin - yCoord)*0.8660254; // cos(30)=0.8660254

    }
I am aware of that I need to add these changes in more places.

Now the plot will be drawn with triangular coordinates in a regular cartesian plot so now I have to take care of the axes and background. My thought to continue from here is to add some new "RectangleEdges" in JCommon (however they will not be particularly rectangular), and move on from there:

RectangleEdge.java

Code: Select all

    /** Left triangle. */
    public static final RectangleEdge LEFT_TRIANGLE 
        = new RectangleEdge("RectangleEdge.LEFT_TRIANGLE");

    /** Right triangle. */
    public static final RectangleEdge RIGHT_TRIANGLE 
        = new RectangleEdge("RectangleEdge.RIGHT_TRIANGLE");
But now I realized that I can't control the aspect ratios of the lengths (in pixels) of the axes, nor can I by default control the size of the dataarea. I want the triangular diagrams equilateral all the time, and the user must be able to resize the window, so I have to be able to do that. It turned out that paradoxoff has released a patch that enables you to control the size of the data area, however that approach shows unexpected behavior because the JFrame does not respect the resizing ChartPanel so the size on screen will not automatically be what you want it to be. Then we have the aspect ratio control, which Dave himself found to be tricky to implement.

So now two essential features are missing and people much more experienced in java than I am find them difficult to implement. Did you hear that sound of me hitting a wall? :)

What to do?

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Re: Adding support for triangular diagrams - input welcome

Post by paradoxoff » Thu Mar 05, 2009 11:31 am

One general hint:
The ternary plot differes from the usual rectangular XYPlot in a number of ways: number of axis (always three), orientation of the axis (one horizontal, the others angular), value range (seems to be alway 0-100 %), orientation of the labels (not necessary parallel to the axis). I think that you will have to change or override most of the XYPlot methods anyways.
I wonder whether it wouldn´t be better to start with a new Plot class that could (but doesn´t have to) extend XYPlot and put all the drawing and calculations inside the new Plot class. There are a couple of "special" plots (e. g. a SpiderWebPlot) that have special drawing requirements and do most of the drawing work by themselves instead of delegating it to the axes and renderers.
The starting point for the drawing of any Plot is always Plot.draw(Graphics2D g2,Rectangle2D area,Point2D anchor,PlotState parentState,PlotRenderingInfo info). You could start from there and develop your own drawing routines completely from scratch (instead of trying to get them into the already existing classes).
That will give you lots of degrees of freedom, among others a possibility to ensure an equal axis length: from the area provided in the Plot.draw(...) method, you can construct a square area that will fit into the original rectangular area (e.g. you could go from 300x500 to 300x300) and do the drawing within this smaller square area.

sammen
Posts: 15
Joined: Mon Feb 02, 2009 9:55 am

Re: Adding support for triangular diagrams - input welcome

Post by sammen » Thu Mar 05, 2009 3:00 pm

Thanks for the answer. I am starting to be convinced that I should at least override XYPlot. :)

At a glance, to me the SpiderWebPlot looks like a very special plot. When it comes to the rendering, I don't think ternary plots differ very much from rectangular. For example, I want the rendering of the data (shapes and lines) in the ternary diagrams to be exactly the same as for the rectangular ones, except for the Java2D coordinates that are calculated a little bit different. The x-axis is exactly the same. The y-axis differs in that it's angled, ticks and labels should be the same (that's why I thought it was a good idea to use the same approach as for the vertical and horizontal axes). Ideally, the user should be able to easily switch between viewing a set of data in both formats, basically without seeing any difference except that the y-axis is tilted 30 degrees, and without losing any functionality.

The axes don't always have to go 0-100%. If you choose axis limits below 100 you might not even want to plot the third axis. If the x- and y-axes go from 0 to 100%, then the third axis is the limit of the allowed values. But if you zoom, there is no such constraint, but you might still want to view it as a triangular diagram, however now the dataarea is a parallelogram (if you don't clip it).

You really have a point though when it comes to controlling the axis lengths. I have to go to a meeting now, but I think I'll have time to think and write more this evening.

I really appreciate that you share your thought on this.

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

Re: Adding support for triangular diagrams - input welcome

Post by david.gilbert » Thu Mar 05, 2009 10:12 pm

I'm with 'paradoxoff' on this...start with a new plot type. It is tempting to want to reuse XYPlot (because so much of it still applies, in the abstract) but it turns out that a lot of the XYPlot code (and the axes and the renderers) *assume* that the translation from (x, y) data values to Java2D coordinates is linear. I think it is better to reuse the concepts (plot, axes, renderers...) but re-implement them with new classes and interfaces. The dataset interface (XYDataset) and classes you can probably reuse directly.
David Gilbert
JFreeChart Project Leader

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

sammen
Posts: 15
Joined: Mon Feb 02, 2009 9:55 am

Re: Adding support for triangular diagrams - input welcome

Post by sammen » Fri Mar 06, 2009 10:13 am

I will do as you wish. Even though I don't immediately see all the complications with my initial approach, I am quite sure I will thank you later.

sammen
Posts: 15
Joined: Mon Feb 02, 2009 9:55 am

Re: Adding support for triangular diagrams - input welcome

Post by sammen » Wed Apr 22, 2009 1:51 pm

I have been spending some time on this now and have come up with something that looks pretty nice, I think.

The TernaryPlot extends Plot, and I have introduced a number of other classes, such as renderers and axes that support the new plot type. All functionality of the XYPlot is not there, however zooming with the mouse works ok and the standard tooltip works ok. Most of the code is copied from the corresponding XY class and slightly altered to fit triangular diagrams.

I have a few things left before I consider my attempt to be something potentially useful, and perhaps the most important thing is to display tooltip based on empty space rather than the actual lines. Take a look at this plot, but ignore the triangles (this plot is not made with "my" code). For some types of labeling and/or tooltip, the interesting parts are the fields between all lines, rather than the data points themselves. The keys of the series surrounding the area will give enough information to determine the tooltip or label text of the actual area. This means that I have to find a way to collect and store that information for the tooltip, and my question is: what do you think would be a suitable way to do this?

Edit: The plot I link to is not made with my code.
Last edited by sammen on Mon Apr 27, 2009 8:17 am, edited 2 times in total.

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

Re: Adding support for triangular diagrams - input welcome

Post by david.gilbert » Sat Apr 25, 2009 8:20 am

The chart looks great! I'm not sure what to recommend for the tooltips. But I'd encourage you to package up the code you have and post it somewhere so that you can start to get some feedback on it...lots of improvements usually flow from that.
David Gilbert
JFreeChart Project Leader

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

sammen
Posts: 15
Joined: Mon Feb 02, 2009 9:55 am

Re: Adding support for triangular diagrams - input welcome

Post by sammen » Sun Apr 26, 2009 9:46 am

Oh. The chart in my previous post is not made in JFreeChart, it's just another example from the web. However I think the charts I have made with the Ternary class look better than the one in the previous post, simply because they have the same "look" as XYPlots (which I think look really nice).

Next week I'll try to get time and post one or more triangular diagrams from my code. Before I submit any code I think I want to clean it up a little and also comment it a little better.

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Re: Adding support for triangular diagrams - input welcome

Post by paradoxoff » Sun Apr 26, 2009 8:40 pm

Congratulations! I am looking forward to see some examples. Though I have no need for this type of plot, I really like the idea of using JFreeChart for scientifc plots.
Concerning the tool tips: if you have the coordinates that describe a certain area (composition of a sepcial alloy or something) you could use the coordinates to create an XYPolygonAnnotation an give that a suitable tool tip text.

sammen
Posts: 15
Joined: Mon Feb 02, 2009 9:55 am

Re: Adding support for triangular diagrams - input welcome

Post by sammen » Mon Apr 27, 2009 8:43 am

Without having looked at it yet, it sounds like XYPolygonAnnotation could be the way to go. I have the coordinates of the areas. The most apparent difficulty I guess would be to handle the cases when the fields cross an axis (meaning that the axis will close the polygon), but maybe that's already there? I'll have a look at it.

I was also thinking about how to structure the classes. Now both TernaryPlot and XYPlot extend Plot, but a lot of code is exactly the same. Should I make an abstract StandardXYPlot and have TernaryPlot and XYPlot extend it? Is there anything in this regard I can do to make it easier to maintain and include updates of the JFreeChart library?

sammen
Posts: 15
Joined: Mon Feb 02, 2009 9:55 am

Re: Adding support for triangular diagrams - input welcome

Post by sammen » Mon Apr 27, 2009 2:26 pm

Here's a simple example of a triangular diagram made with my code. It has no labels, but the tooltip shows the value and series key if I hover the mouse on the lines.

In this hypothetical case we can imagine that in the field below the bottommost line, only a gas phase phase is stable. Above the uppermost line only liquid is stable. Between the lines, both liquid and gas are stable together in a mixture. What I want to do now is to make the code know that and show that as a tooltip, rather than showing the stable state corresponding to one line. In this case I think it will be quite tricky to code it, because e.g. the liquid phase is limited by all three diagram edges, as well as the actual line.

Image

siva.nookala
Posts: 1
Joined: Mon Jan 17, 2011 4:41 am
antibot: No, of course not.

Re: Adding support for triangular diagrams - input welcome

Post by siva.nookala » Mon Jan 17, 2011 4:48 am

Hello sammen,

Greetings. We have a requirement in our project to draw the ternary plots. It would be of great help for us if you can share the code you developed for ternary plot. I have searched for it in the whole forum but could not find the same.

Thanks for your help.

Locked