src/JsPlot3D.js
/**
     * plots a function into the container as 3D Plot. It will execute the function with varying parameters a few times
     * @param {function} foo function. For example: function(x, z) { return x+z }
     * @param {object} options json object with one or more of the following parameters:
     * - mode {string}: "barchart", "scatterplot" or "polygon"
     * - normalizeX2 {boolean}: if false, data will not be normalized. Datapoints with high values will be very far away then on the X2 Axis (y)
     * - title {string}: title of the data
     * - fraction {number}: between 0 and 1, how much of the dataset should be plotted.
     * - x2frac {number}: by how much to divide the datapoints x2 value (y) to fit into [-1;1]. will be overwritten if normalization is on
     * - barchartPadding {number}: how much space should there be between the bars? Example: 0.025
     * - dataPointSize {number}: how large the datapoint should be. Default: 0.04
     * - x1title {string}: title of the x1 axis
     * - x2title {string}: title of the x2 axis
     * - x3title {string}: title of the x3 axis
     * - hueOffset {number}: how much to rotate the hue of the labels. between 0 and 1. Default: 0
     * - keepOldPlot {boolean}: don't remove the old datapoints/bars/etc. when this is true
     * - updateOldData {boolean}: if false, don't overwrite the dataframe that is stored in the oldData-object
     * - barSizeThreshold {number}: smallest allowed y value for the bars. Smaller than that will be hidden. Between 0 and 1. 1 Hides all bars, 0 shows all. Default 0  
     * - numberDensity {number}: how many numbers to display when the length (xLen, yLen or zLen) equals 1. A smaller axis displays fewer numbers and a larger axis displays more.
     */
plots a function into the container as 3D Plot. It will execute the function with varying parameters a few times
@param {function} foo function.
plots a function into the container as 3D Plot . It will execute the function with varying parameters a few times @param { function } foo function .
plotFunction(foo, options ={})
    {
        let mode = POLYGON_MODE
        let x2frac = 1
        let normalizeX2 = true
        let title = "function"
        let x1title = "1. param"
        let x2title = "return value"
        let x3title = "2. param"
        if(this.isAnimated())
            options.fastForward = true 
        if(options.mode != undefined) mode = options.mode
        if(options.x2frac != undefined) x2frac = options.x2frac
        if(options.normalizeX2 != undefined) normalizeX2 = options.normalizeX2
        if(options.title != undefined) title = options.title
        if(options.x1title != undefined) x1title = options.x1title
        if(options.x2title != undefined) x2title = options.x2title
        if(options.x3title != undefined) x3title = options.x3title
        if(!foo)
            return console.error("first param of plotFormula (foo) is undefined or empty")
        this.clearCheckString()
        options.header = false
        options.title = title
        options.x1title = x1title
        options.x2title = x2title
        options.x3title = x3title
        if(mode == POLYGON_MODE)
        {
            this.oldData.options.mode = POLYGON_MODE
            let hueOffset = 0
            let numberDensity = 3
            if(this.checkNumber("hueOffset", options.hueOffset)) hueOffset = options.hueOffset
            if(this.checkNumber("numberDensity", options.numberDensity)) numberDensity = options.numberDensity
            let colors = {hueOffset}
            let normalization = {normalizeX2, x2frac}
            let appearance = {numberDensity}
            let dimensions = this.dimensions
            this.populateLegend({x1title, x2title, x3title, title})
            polygon(foo, this, colors, normalization, appearance, dimensions)
        }
        else
        {
            let df = new Array(this.dimensions.xRes * this.dimensions.zRes)
            let i = 0
            let y = 0
            for(let x = 0; x < this.dimensions.xRes; x++)
            {
                for(let z = 0; z < this.dimensions.zRes; z++)
                {
                    y = foo(x/this.dimensions.xRes, z/this.dimensions.zRes)
                    df[i] = new Float32Array(3)
                    df[i][0] = x/this.dimensions.xRes 
                    df[i][1] = y 
                    df[i][2] = z/this.dimensions.zRes 
                    i++
                }
            }
            options.colorCol = 1 
            this.plotDataFrame(df, 0, 1, 2, options)
        }
    }
plotFunction ( foo , options = { } ) { let mode = POLYGON_MODE let x2frac = 1 let normalizeX2 = true let title = "function" let x1title = "1. param" let x2title = "return value" let x3title = "2. param" if ( this . isAnimated ( ) ) options . fastForward = true if ( options . mode != undefined ) mode = options . mode if ( options . x2frac != undefined ) x2frac = options . x2frac if ( options . normalizeX2 != undefined ) normalizeX2 = options . normalizeX2 if ( options . title != undefined ) title = options . title if ( options . x1title != undefined ) x1title = options . x1title if ( options . x2title != undefined ) x2title = options . x2title if ( options . x3title != undefined ) x3title = options . x3title if ( ! foo ) return console . error ( "first param of plotFormula (foo) is undefined or empty" ) this . clearCheckString ( ) options . header = false options . title = title options . x1title = x1title options . x2title = x2title options . x3title = x3title if ( mode == POLYGON_MODE ) { this . oldData . options . mode = POLYGON_MODE let hueOffset = 0 let numberDensity = 3 if ( this . checkNumber ( "hueOffset" , options . hueOffset ) ) hueOffset = options . hueOffset if ( this . checkNumber ( "numberDensity" , options . numberDensity ) ) numberDensity = options . numberDensity let colors = { hueOffset } let normalization = { normalizeX2 , x2frac } let appearance = { numberDensity } let dimensions = this . dimensions this . populateLegend ( { x1title , x2title , x3title , title } ) polygon ( foo , this , colors , normalization , appearance , dimensions ) } else { let df = new Array ( this . dimensions . xRes * this . dimensions . zRes ) let i = 0 let y = 0 for ( let x = 0 ; x < this . dimensions . xRes ; x ++ ) { for ( let z = 0 ; z < this . dimensions . zRes ; z ++ ) { y = foo ( x / this . dimensions . xRes , z / this . dimensions . zRes ) df [ i ] = new Float32Array ( 3 ) df [ i ] [ 0 ] = x / this . dimensions . xRes df [ i ] [ 1 ] = y df [ i ] [ 2 ] = z / this . dimensions . zRes i ++ } } options . colorCol = 1 this . plotDataFrame ( df , 0 , 1 , 2 , options ) } }
plots a function into the container as 3D Plot.
plots a function into the container as 3D Plot .
// default options // performance increase by using fastForward (but it's only very small actually) // overwrite if available // so that plotCsvString knows that the dataFrame did not originate from plotCsvString // force the following settings: // the deafult titles here are different from plotDataFrame, which is being called later to actually show the formula. So the default titles // need to be passed to plotDataFrame inside the options object. Or of course the user has set them in the options parameter. in That case those variables // contain the user setting. //plotFunction //-------------------------// //         Polygon         // //-------------------------// // indicates, that a polygon is currently being plotted, which also indicates that a formula is being plotted // creating the legend. As this polygon mode does not forward a dataframe to plotDataFrame, creating the legend has to be handled here in plotFormula // the y-values are calculated inside the call to polygon, so no df is passed over to this function // note that updating the numbers along the axes is handled in the call to polygon //plotFunction //-------------------------// //     default action      // //-------------------------// // mode unrecognized, maybe plotDataFrame knows what to do // create a dataframe and send it to plotDataFrame // multiply those two values for the ArraySize because that many datapoints will be created // three values (x, y and z) that are going to be stored in the dataframe // line number in the new dataframe // calculate y. y = f(x1, x2) // store the datapoint // store the datapoint // store the datapoint // colorCol is the index that is used to colorate the datapoints. // The index of 1 means the y value contains the number that is converted to a color // it is 1 because of "df[i][1] = y" above // continue plotting this DataFrame