Java source code of 'jhplot.F3D'

/**
*    Copyright (C)  DataMelt project. The jHPLot package by S.Chekanov and Work.ORG
*    All rights reserved.
*
*    This program is free software; you can redistribute it and/or modify it under the terms
*    of the GNU General Public License as published by the Free Software Foundation; either
*    version 3 of the License, or any later version.
*
*    This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
*    without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*    See the GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along with this program;
*    if not, see .
*
*    Additional permission under GNU GPL version 3 section 7:
*    If you have received this program as a library with written permission from the DataMelt team,
*    you can link or combine this library with your non-GPL project to convey the resulting work.
*    In this case, this library should be considered as released under the terms of
*    GNU Lesser public license (see ),
*    provided you include this license notice and a URL through which recipients can access the
*    Corresponding Source.
**/
package jhplot;

import hep.aida.IFunction;
import java.io.Serializable;

import jhplot.gui.HelpBrowser;
import jhplot.math.exp4j.*;


/**
 * Create 3D function  using 3 independent variables: x,y,z.
 *
 * 

* One can enabled fast math calculation using @see jhplot.HParam. * For example, setting jhplot.HParam.setMath(true) makes calculation of elementary functions * a factot 4-5 faster than using the standard Java Math, with precision of E-14. *

* *

* Operators and functions *

* the following operators are supported: *

    *
  • Addition: '2 + 2'
  • *
  • Subtraction: '2 - 2'
  • *
  • Multiplication: '2 * 2'
  • *
  • Division: '2 / 2'
  • *
  • Exponential: '2 ^ 2' or ** (raise to a power)
  • *
  • Unary Minus,Plus (Sign Operators): '+2 - (-2)'
  • *
  • Modulo: '2 % 2'
  • *
* the following functions are supported: *
    *
  • abs: absolute value
  • *
  • acos: arc cosine
  • *
  • asin: arc sine
  • *
  • atan: arc tangent
  • *
  • cbrt: cubic root
  • *
  • ceil: nearest upper integer
  • *
  • cos: cosine
  • *
  • cosh: hyperbolic cosine
  • *
  • exp: euler's number raised to the power (e^x)
  • *
  • floor: nearest lower integer
  • *
  • log: logarithmus naturalis (base e)
  • *
  • sin: sine
  • *
  • sinh: hyperbolic sine
  • *
  • sqrt: square root
  • *
  • tan: tangent
  • *
  • tanh: hyperbolic tangent
  • *
* It also recognizes the pi (or Pi) values. * * @author S.Chekanov * */ public class F3D extends DrawOptions { /** * */ private static final long serialVersionUID = 1L; private FProxy proxy; final int maxpoints = 200; private String title="F3D"; private Expression calc = null; private ExpressionBuilder function = null; /** * Create a function in 3D for evaluation. * The function may have up to 3 independent variables: x,y,z. * This is unranged function. * * Operators and functions *

* the following operators are supported: *
    *
  • Addition: '2 + 2'
  • *
  • Subtraction: '2 - 2'
  • *
  • Multiplication: '2 * 2'
  • *
  • Division: '2 / 2'
  • *
  • Exponential: '2 ^ 2' or ** (raise to a power)
  • *
  • Unary Minus,Plus (Sign Operators): '+2 - (-2)'
  • *
  • Modulo: '2 % 2'
  • *
* the following functions are supported: *
    *
  • abs: absolute value
  • *
  • acos: arc cosine
  • *
  • asin: arc sine
  • *
  • atan: arc tangent
  • *
  • cbrt: cubic root
  • *
  • ceil: nearest upper integer
  • *
  • cos: cosine
  • *
  • cosh: hyperbolic cosine
  • *
  • exp: euler's number raised to the power (e^x)
  • *
  • floor: nearest lower integer
  • *
  • log: logarithm natural (base e)
  • *
  • sin: sine
  • *
  • sinh: hyperbolic sine
  • *
  • sqrt: square root
  • *
  • tan: tangent
  • *
  • tanh: hyperbolic tangent
  • *
* It also recognizes the pi (or Pi) values; * @param name * String representing the function */ public F3D(String name) { this(name,0.0,0.0,0.0,0.0,0.0,0.0); } /** * Create a function in 3D. Uses 500 points between min and max value for * evaluation. The function may have up to 3 independent variables in it * (x,y,z). This is ranged function. * * Operators and functions *

* the following operators are supported: *
    *
  • Addition: '2 + 2'
  • *
  • Subtraction: '2 - 2'
  • *
  • Multiplication: '2 * 2'
  • *
  • Division: '2 / 2'
  • *
  • Exponential: '2 ^ 2' or ** (raise to a power)
  • *
  • Unary Minus,Plus (Sign Operators): '+2 - (-2)'
  • *
  • Modulo: '2 % 2'
  • *
* the following functions are supported: *
    *
  • abs: absolute value
  • *
  • acos: arc cosine
  • *
  • asin: arc sine
  • *
  • atan: arc tangent
  • *
  • cbrt: cubic root
  • *
  • ceil: nearest upper integer
  • *
  • cos: cosine
  • *
  • cosh: hyperbolic cosine
  • *
  • exp: euler's number raised to the power (e^x)
  • *
  • floor: nearest lower integer
  • *
  • log: logarithm natural (base e)
  • *
  • sin: sine
  • *
  • sinh: hyperbolic sine
  • *
  • sqrt: square root
  • *
  • tan: tangent
  • *
  • tanh: hyperbolic tangent
  • *
* * * @param name * String representing the function. * @param Xmin * Min value in X * @param Xmax * Max value in X * @param Ymin * Min value in Y * @param Ymax * Max value in Y * @param Zmin * Min value in Z * @param Zmax * Max value in Y * */ public F3D(String title, String name, double Xmin, double Xmax, double Ymin, double Ymax, double Zmin, double Zmax) { proxy = new FProxy(3,title, name, null, new double[]{Xmin,Xmax,Ymin,Ymax,Zmin,Zmax}, maxpoints, true); function = new ExpressionBuilder(proxy.getName()); try { calc = (function.variables("x","y","z")).build(); } catch (IllegalArgumentException e) { proxy.setParsed(false); jhplot.utils.Util.ErrorMessage("Failed to parse function " + name+" Error:"+e.toString()); } } /** * Build a 3D function. Title set to its name. * Ranged function. * * @param name * @param Xmin * @param Xmax * @param Ymin * @param Ymax * @param Zmin * @param Zmax */ public F3D(String name, double Xmin, double Xmax, double Ymin, double Ymax, double Zmin, double Zmax) { this(name,name,Xmin,Xmax,Ymin,Ymax,Zmin,Zmax); } /** * Create a function in 3D from a AIDA IFunction. * * @param title * title * @param name * String representing the function. * @param iname * input AIDA function * @param Xmin * Min value in X * @param Xmax * Max value in X * @param Ymin * Min value in Y * @param Ymax * Max value in Y * @param Zmin * Min value in Z * @param Zmax * Max value in Y * */ public F3D(String title, String name, IFunction iname, double Xmin, double Xmax, double Ymin, double Ymax, double Zmin, double Zmax) { proxy = new FProxy(3,title, name, iname, new double[]{Xmin,Xmax,Ymin,Ymax,Zmin,Zmax}, maxpoints, true); this.title = title; } public F3D(String name, IFunction iname, double Xmin, double Xmax, double Ymin, double Ymax, double Zmin, double Zmax) { } /** * Initialize function from proxy. * @param f */ public F3D(FProxy f) { if (f.getType() != 3) { jhplot.utils.Util.ErrorMessage("Error in parsing F3D. Wrong function type! " + f.getName()); return; } proxy=f; setTitle(proxy.getTitle()); } /** * Create a function in 3D from a AIDA IFunction. * @param iname * input AIDA function * @param Xmin * Min value in X * @param Xmax * Max value in X * @param Ymin * Min value in Y * @param Ymax * Max value in Y * @param Zmin * Min value in Z * @param Zmax * Max value in Y * */ public F3D(IFunction iname, double Xmin, double Xmax, double Ymin, double Ymax, double Zmin, double Zmax) { this("IFunction",iname,Xmin,Xmax,Ymin,Ymax,Zmin,Zmax); } /** * Evaluate a function at a specific point in (x,y,z) * * @param x * value in x for evaluation * @param y * value in y for evaluation * @param z * value in z for evaluation * * @return function value at (x,y,z) */ public double eval(double x, double y, double z) { double h = 0; IFunction iname=proxy.getIFunction(); boolean isParsed=proxy.isParsed(); String name=proxy.getName(); // jPlot function first if (iname == null && (function == null || isParsed == false)) { jhplot.utils.Util.ErrorMessage("eval(): Function was not parsed correctly!"); return h; } // evaluate function if (iname == null && function != null && isParsed == true) { try { calc.setVariable("x", x); calc.setVariable("y", y); calc.setVariable("z", z); h = calc.evaluate(); } catch (Exception e) { jhplot.utils.Util.ErrorMessage("Failed to evaluate function " + name+" Error:"+e.toString()); // System.out.println("Failed to evaluate function:" + name); } } // start AIDA function if (iname != null && iname.dimension() == 3) { try { double[] xx = new double[iname.dimension()]; xx[0] = x; xx[1] = y; xx[2] = z; h = iname.value(xx); } catch (Exception e) { // System.out.println("Failed to evaluate function!"); jhplot.utils.Util.ErrorMessage("Failed to evaluate function " + name+" Error:"+e.toString()); } } // end IFunction return h; } /** * Set a title * * @param title * Title */ public void setTitle(String title) { this.title = title; } /** * Get the title * * @return Title */ public String getTitle() { return this.title; } /** * Set Min in X * * @param min * Min value */ public void setMinX(double min) { proxy.setLimit(0,min); } /** * Get Min value in X * * @return Min value in X */ public double getMinX() { double[] d= proxy.getLimits(); return d[0]; } /** * Set Min value in Y * * @param min * Min value in Y */ public void setMinY(double min) { proxy.setLimit(2,min); } /** * Set Min value in Z * * @param min * Min value in Z */ public void setMinZ(double min) { proxy.setLimit(4,min); } /** * Get Min value in Y * * @return Min value in Y */ public double getMinY() { double[] d= proxy.getLimits(); return d[2]; } /** * Get Min value in Z * * @param Min * value in Z */ public double getMinZ() { double[] d= proxy.getLimits(); return d[4]; } /** * Set Max value in X * * @param max * Max value in X */ public void setMaxX(double max) { proxy.setLimit(1,max); } /** * Show online documentation. */ public void doc() { String a=this.getClass().getName(); a=a.replace(".", "/")+".html"; new HelpBrowser( HelpBrowser.JHPLOT_HTTP+a); } /** * Set Max value in Z * * @param max * Max value in Z */ public void setMaxZ(double max) { proxy.setLimit(5,max); } /** * Sets a name of the function, i.e. what will be used for evaluation * * @param name * Name */ public void setName(String name) { proxy.setName(name); } /** * Get the name of the function used for evaluation * * @return Name */ public String getName() { return proxy.getName(); } /** * Get Max value in X * * @return Max value in X */ public double getMaxX() { double[] d= proxy.getLimits(); return d[1]; } /** * Set Max value in Z * * @return max Max value in Z */ public double getMaxZ() { double[] d= proxy.getLimits(); return d[5]; } /** * Set Max value in Y * * @param max * Max value in Y */ public void setMaxY(double max) { proxy.setLimit(3,max); } /** * Get Max value in Y * * @return Max value in Y */ public double getMaxY() { double[] d= proxy.getLimits(); return d[1]; } /** * Get the number of points * * @param bins * Number of points */ public void setPoints(int bins) { proxy.setPoints(bins); } /** * Get the number of points for evaluation of a function * * @return Number of points */ public int getPoints() { return proxy.getPoints(); } /** * Return parsed functional expression. * * @return function * */ public Expression getParse() { return calc; } /** * Parse the function. * @return true if parsed without problems. **/ public boolean parse() { boolean isParsed=proxy.isParsed(); String name=proxy.getName(); try { function = new ExpressionBuilder(name); calc=(function.variables("x","y","z")).build(); proxy.setParsed(true); } catch (IllegalArgumentException e) { proxy.setParsed(false); //System.err.println("Failed to parse function " + this.name+" Error:"+e.toString()); jhplot.utils.Util.ErrorMessage("Failed to parse function " + name+" Error:"+e.toString()); } return isParsed; } /** * Get Jaida function * * @return */ public IFunction getIFunction() { return proxy.getIFunction(); } /** * If the function is parsed correctly, return true. Use this check before * drawing it. * * @return true if parsed. */ public boolean isParsed() { return proxy.isParsed(); } /** * Get the proxy of this function used for serialization * and non-graphical representations. * * @param proxy proxy of this function. */ public FProxy get(){ return proxy; } /** * Replace abstract parameter with the value (double). Case sensitive! * * @param parameter * parameter name * @param value * value to be inserted */ public void setPar(String parameter, double value) { String s1 = Double.toString(value); String name=proxy.getName(); proxy.setName(name.replaceAll(parameter, s1)); } /** * Get this function as a string. * * @return Convert to string. */ public String toString() { String tmp = "F3D:" + proxy.getName(); double[] d = proxy.getLimits(); boolean isParsed = proxy.isParsed(); double Xmin = d[0]; double Xmax = d[1]; double Ymin = d[2]; double Ymax = d[3]; double Zmin = d[2]; double Zmax = d[3]; int points = proxy.getPoints(); tmp = tmp + " (title=" + getTitle() + ", n=" + Integer.toString(points) + ", minX=" + Double.toString(Xmin) + ", maxX=" + Double.toString(Xmax) + ", minY=" + Double.toString(Ymin) + ", maxY=" + Double.toString(Ymax) + ", " + Double.toString(Xmax) + ", minZ=" + Double.toString(Zmin) + ", maxZ=" + Double.toString(Zmax) + ", " + Boolean.toString(isParsed) + ")"; return tmp; } }