001: /*
002: JOpenChart Java Charting Library and Toolkit
003: Copyright (C) 2001 Sebastian Müller
004: http://jopenchart.sourceforge.net
005:
006: This library is free software; you can redistribute it and/or
007: modify it under the terms of the GNU Lesser General Public
008: License as published by the Free Software Foundation; either
009: version 2.1 of the License, or (at your option) any later version.
010:
011: This library is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public
017: License along with this library; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019:
020: FunctionPlotter.java
021: Created on 7. September 2001, 17:14
022: */
023:
024: package de.progra.charting.model;
025:
026: import org.nfunk.jep.JEP;
027:
028: /**
029: * This class can be used to create a ChartDataModel from a mathematical
030: * function. A Python interpreter implemented in Java is called to calculate
031: * the function values. Therefore, I didn't need to implement a parsing
032: * algorithm. Of course, you need to know the Python syntax for mathematical
033: * functions. The quadratical function <code>5x<sup>2</sup>-3x+4</code> e.g.
034: * would be written as <code>5*x**2-3*x+4</code>. Please note, that it takes
035: * approx. 1 s to plot a quadratical function like this computing 2000 single
036: * values.
037: * @author mueller
038: * @version 1.0
039: */
040: public class FunctionPlotter {
041:
042: /** Creates new FunctionPlot */
043: private FunctionPlotter() {
044: }
045:
046: /** This method creates a new ChartDataModel from the computed
047: * function data. In order to compute the needed values, a Python script is
048: * created using the provided parameters and is executed afterwards:<p>
049: <pre><code>
050: String pyfile = "" +
051: "AMOUNT = "+amount+"\n"+
052: "columns = []\n"+
053: "model = []\n"+
054: "lowrange = "+lowrange+"\n"+
055: "highrange = "+highrange+"\n"+
056: "for i in range(AMOUNT) :\n"+
057: " x = lowrange + i * (float(abs(highrange - lowrange)) / AMOUNT)\n"+
058: " columns.append(x)\n"+
059: " model.append("+function+")\n";
060:
061: interp.exec(pyfile);
062: </code></pre>
063: Finally the values are extracted via the PythonInterpreter:<p>
064: <pre><code>
065: pymodel[0] = (double[])interp.get("model", double[].class);
066: pycolumns = (double[])interp.get("columns", double[].class);
067: </code></pre>
068: * @param lowrange the lower x-value to begin from
069: * @param highrange the highest x-value to reach
070: * @param amount the amount of values that should be computed (2000 is
071: * a good value for smooth curves)
072: * @param function the mathematical function in Python notation
073: * @param rows the array with the DataSet title
074: * @throws IllegalArgumentException if the function contains more than
075: * one variable.
076: */
077:
078: public static DefaultChartDataModel createChartDataModelInstance(
079: double lowrange, double highrange, int amount,
080: String function, String[] rows) {
081: double x = 0.0;
082: JEP jep = new JEP();
083: jep.addStandardConstants();
084: jep.addStandardFunctions();
085:
086: jep.parseExpression(function);
087:
088: String[] vars = jep.getVariables();
089: String var = "x";
090:
091: if (vars.length > 1)
092: throw new IllegalArgumentException(
093: "The supplied function contains more than one variable.");
094:
095: if (vars.length == 1)
096: var = vars[0];
097:
098: double[][] model = new double[1][amount];
099: double[] columns = new double[amount];
100:
101: for (int i = 1; i <= amount; i++) {
102: x = lowrange
103: + i
104: * ((double) Math.abs(highrange - lowrange) / amount);
105: columns[i - 1] = x;
106: jep.addVariable(var, x);
107: model[0][i - 1] = jep.getValue();
108: //System.out.println("** Calc("+columns[i-1]+") = "+model[0][i-1]);
109: }
110:
111: return new DefaultChartDataModel(model, columns, rows);
112: }
113:
114: /** This method creates a new ChartDataModel from the computed
115: * function data. This implementation automatically uses the function
116: * as DataSet title.
117: * @param lowrange the lower x-value to begin from
118: * @param hirange the highest x-value to reach
119: * @param amount the amount of values that should be computed (2000 is
120: * a good value for smooth curves)
121: * @param function the mathematical function in Python notation
122: */
123:
124: public static DefaultChartDataModel createChartDataModelInstance(
125: double lowrange, double hirange, int amount, String function) {
126: return createChartDataModelInstance(lowrange, hirange, amount,
127: function, new String[] { function });
128: }
129:
130: }
|